    '// ========================================================================= '
    '// ------------------------------------------------------------------------- '
    '//!				\file		CMain.vb
    '			        \date		june 2010
    '			        \author		TNick
    '
    '			        \brief		
    '
    '
    '   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    '   This file is considered universal knowledge. No restrictions
    '   are imposed; use as you see fit.
    '   Please read ReadMe.txt and Licence.txt in root folder
    '   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    '
    '   
    ' debug info is all in english
    '// ------------------------------------------------------------------------- '
    '// ========================================================================= '


                            'Problems

    ' grid


    ' points
    ' - edit: smart


    ' div area
    ' - ask for dir after each break


    ' Symbols
    ' - slope lines failing on some occasions


    ' Dimensions


    ' Images


    ' Tables

    '// ------------------------------------------------------------------------- '
    '// ========================================================================= '

    '//
    '//
    '//
    '//
    '//  IMPORTS     ------------------------------------------------------------ '
    #Region "Imports"
    
        Imports System
        Imports System.IO
        Imports System.Net
        Imports System.Text
        Imports Microsoft.Win32

        Imports Autodesk.AutoCAD.Runtime
        Imports Autodesk.AutoCAD.ApplicationServices
        Imports Autodesk.AutoCAD.EditorInput
        Imports Autodesk.AutoCAD.DatabaseServices
        Imports Autodesk.AutoCAD.Geometry
        Imports Autodesk.AutoCAD.Customization
        Imports Autodesk.AutoCAD.Colors
        Imports Autodesk.AutoCAD.GraphicsSystem
        Imports System.Runtime.InteropServices
    

    #End Region
    '//  IMPORTS     ============================================================ '
    '//
    '//
    '//
    '//
    '//  DEFINITIONS    --------------------------------------------------------- '
    
    
        '// this enumeration expresses the strings in a unique form
        Public enum TX '// the coments list the strings in english
            LANGNAME     '//     "English"
            OK           '//     "OK"
            CANCEL       '//     "Cancel"
            EXC_IN       '//     "Exception in "
            GRID_INFO    '//     "Utility for grid creation"
            NO_LDESCR    '//     "No description is provided for this application"
            NO_NAME      '//     "(unnamed)"
            CSTG         '//     "Current settings for "
            CROSS        '//     "Cross"
            BORDER       '//     "Border"
            VALUES       '//     "Values"
            HTEXT        '//     "Text height"
            HLINE        '//     "Line height"
            SPAN         '//     "Span"
            MODEL        '//     "Model"
            PAPER        '//     "Paper"
            OPTIONS      '//     "Options"
            SETTINGS     '//     "Settings"
            GRID_ERROVRF '//     "Current settings conclude ..."
            VPALIGN      '//     "Non WCS aligned VP."
            OPABORT      '//     "Operation aborted."
            YES          '//     "Yes"
            NO           '//     "No"
            DSTBETWEEN   '//     "Distance between"
            MARKERS      '//     "Markers"
            MARKSIZE     '//     "Marker size"
            LABELS       '//     "Labels"
            LBLSIZE      '//     "Label size"
            FPOINT       '//     "First point", _
            SPOINT       '//     "Second point", _
            TPOINT       '//     "Third point", _
            ERR_CMDI     '//     "Command not implemented yet"
            SELVP        '//     "Select viewport"
            ERR_OBJTY    '//     "Unexpected object type"
            ERR_PTCLOSE  '//     "Points are too close to each other"
            PT3D_INFO    '//     "3D points manager"
            SYM_INFO     '//     "Symbols manager"
            IDB_INFO     '//     "Image database"
            PAREA_INFO   '//     "Polyline area tools"
            DIM_INFO     '//     "Dimensions"
            ERR_FILE     '//     "The file does not exist"
            IMPORT       '//     "Import"
            EXPORT       '//     "Export"
            NAME         '//     "Name"
            TYPE         '//     "Type"
            MODIFIED     '//     "Modified"
            FOLDER       '//     "Folder"
            PT3D_EDEC    '//     "A decimal separator must be specified"
            PT3D_EFLD    '//     "At least one field separator must be specified"
            DECSEP       '//     "Decimal separator"
            FLDSEP       '//     "Field separators"
            SPACE        '//     "Space"
            NORTH        '//     "North"
            EAST         '//     "East"
            HEIGHT       '//     "Height"
            DESCR        '//     "Description"
            ERR_EMTX     '//     "Text field is empty"
            PT3D_EDUPL   '//     "This separator is already present in the list"
            CONTENT      '//     "Content"
            ADD          '//     "Add"
            REMOVE       '//     "Remove"
            WARNING      '//     "Warning"
            STGUNCHG     '//     "The modifications to the settings are not saved!"
            PT3D_LASTI   '//     "Last imported"
            PT3D_LASTE   '//     "Last exported"
            NOTFILEFLD   '//     "The text is not the path to a file or folder"
            LINE         '//     "Line"
            WORD         '//     "Word"
            PT3D_EIMP    '//     "Error in file content"
            PT3D_ENE     '//     "At least a North and an East must be specified"
            PTNR         '//     "Point number"
            PT3D_IMPOK   '//     "A number of {0:d} points were imported"
            LAYFOR       '//     "Layer for:"
            MARKER       '//     "Marker"
            CREATEBLK    '//     "Create block"
            BLKNAME      '//     "Block name"
            ERR_WRONGBLK '//     "Inappropriate block"
            BLOCK        '//     "Block"
            SEPS         '//     "Separators"
            TEXT         '//     "Text"
            FORMAT       '//     "Format"
            LAYS         '//     "Layers"
            IGNERR       '//     "Ignore errors"
            CREATEENT    '//     "Create entities"
            STYLE        '//     "Style"
            PT3D_ECREATE '//     "Error while creating the point"
            PT3D_IMPFAIL '//     "{0:d} points had errors"
            ENOTNUM      '//     "Value is not numeric"
            EWRITE       '//     "Error writing to file"
            PT3D_NPT     '//     "No point in current selection. Scanning entire file..."
            PT3D_EBLK    '//     "Active drawing does not contain target block ({0})"
            PT3D_EXPOK   '//     "A number of {0:d} points were exported"
            PT3D_EXPLDOK '//     "A number of {0:d} points were exploded"
            PT3D_EDITDOK '//     "A number of {0:d} points were edited"
            EXPLODE      '//     "Explode"
            EDIT         '//     "Edit"
            POINT        '//     "Point"
            POLY         '//     "Polyline"
            CONTOUR      '//     "Contour"
            REDISP       '//     "Redisplay"
            ADDIMG       '//     "Add image"
            ADDFOLD      '//     "Add folder"
            SHOWDBF      '//     "Show database"
            DBFPATH      '//     "Database path"
            PICKPOINT    '//     "Pick point"
            FILE         '//     "File"
            PATH         '//     "Path"
            SCALE        '//     "Scale"
            ROT          '//     "Rotation"
            IMGE_DB      '//     "Could not start database"
            IMGE_EMPTY   '//     "Database is empty"
            IMGE_NOI     '//     "No images were found at that location"
            IMGE_DIC     '//     "Could not create image dictionary"
            ERR_DBOBJ    '//     "Could not retrive database object"
    ERR_NOICHC   '//     "No images in cache"
    ERR_DBED     '//     "Database editor could not be started"
    SEL_POLY     '//     "Select Polyline"
    ESEL_POLY    '//     "Only Polyline objects are allowed"
    IMGSERCH     '//     "Raster image search in progress..."
    SEL_IMG      '//     "Select raster image"
    ESEL_IMG     '//     "Only raster image objects are allowed"
    IMG_FND      '//     "Image found in database. Updating..."
    IMG_FNDP     '//     "Image found in on another path..."
    SELPTH       '//     "Select the path to use"
    CRMARKER     '//     "Create marker"
    CRTEXT       '//     "Create text"
    INSIDE       '//     "Inside"
    DBF          '//     "Database"
    VIEW         '//     "View"
    CHOOSE       '//     "Choose"
    SELPYTOMOD   '//     "Select polyline to modify"
    PICKPONSIDE  '//     "Pick point on a side"
    ERR_PTONL    '//     "Point must not be part of the line"
    ERR_P3PT     '//     "Polyline must have at least 3 points"
    ERR_AREASMALL '//     "The area is too small"
    ERR_PD_AHP   '//     "Requested area is larger than the area of polyline ({0})"
    TRGAREA      '//     "Target area"
    BYDIR        '//     "By direction"
    BYFIXPT      '//     "By fixed point"
    OFFSET       '//     "Offset"
    MOVEPT       '//     "Move one point"
    OFFRNG       '//     "Offset range"
    AFOUND       '//     "Area {1} was found after {0} iterations"
    ANOTFOUND    '//     "Area was not found after {0} iterations"
    MAXITER      '//     "Maximum number of iterations"
    LIST         '//     "List"
    PA_CAPLIST   '//     "List of areas to construct"
    INPUT        '//     "Input"
    OUTPUT       '//     "Output"
    PA_ASKDIR    '//     "Ask for directions after each step"
    AREA         '//     "Area"
    ERRORIN      '//     "Error in"
    SKIP         '//     "Skip"
    ERR_PALST    '//     "Area list could not be parsed"
    AREADISPLAY  '//     "A = {0} mp"
    ERR_PTNOTONP '//     "Point must be part of the polyline"
    PICKPTOMOVE  '//     "Pick point to move"
    PREVDIR      '//     "Previous"
    ERR_PD_ASMAL '//     "Requested area too small"
    ERR_PLYLNS   '//     "Polyline may consist only of lines"
    ERR_PLYINTI  '//     "Object intersects itself at offset {0}"
    ERR_PLYINT   '//     "Object intersects itself"
    ERR_FUNKY    '//     "Operation resulted in an unforeseen result"
    PICKBASEP    '//     "Pick base point"
    PICKDIRINS   '//     "Pick point near the side to consider"
    GRIDMODEL    '//     "Grid in model"
    GRIDPAPER    '//     "Grid in paper"
    PICK         '//     "Pick"
    ERR_GETIMGXL '//     "Could not retrive image info at row {0}"
    MAXGRIDOBJ   '//     "Maximum grid objects"
    GRIDRSLT_B   '//     "{0} elements on border", _
    GRIDRSLT_I   '//     "{0} elements inside", _
    INSERT       '//     "Insert"
    INSERTALLSY  '//     "Insert all symbols"
    SYMPERLINE   '//     "Symbols per line"
    ALL          '//     "All"
    GRID_ENONE   '//     "No point is visible in selected area", _
    GRID         '//     "Grid"
    CLOSE        '//     "Close"
    GENSTG       '//     "General Settings"
    MODULES      '//     "Modules"
    VER          '//     "Version"
    TIP          '//     "Tip"
    NOSEL        '//     "(no description)"
    LANG         '//     "Language"
    DEBUGMODE    '//     "Debug mode"
    ALERTU       '//     "Alert user"
    INFORMU      '//     "Inform user"
    USEPROMPT    '//     "Use prompt"
    USEPOPUP     '//     "Use popup"
    NONE         '//     "(none)"
    DBGPRINT     '//     "Debug Output"
    LOG          '//     "Log"
    PROMPT       '//     "Prompt"
    LOGPROMPT    '//     "Log and Prompt"
    SELFILE      '//     "Select file"
    PROGRESS     '//     "Progress"
    FSK_PT3D     '//     "3D points"
    DIMS         '//     "Dimensions"
    IMGDBF       '//     "Image database"
    SRCRES       '//     "Search results"
    POLYAREA     '//     "Polyline area"
    SYMBOLS      '//     "Symbols"
    SYMLIST      '//     "List of symbols"
    SOURCE       '//     "Source"
    PROPERT      '//     "Properties"
    CMDS         '//     "Commands"
    SY_IMPDEF    '//     "Import definition"
    PLACE1       '//     "Place one"
    ONPOLY       '//     "On polyline"
    ONDIR        '//     "On direction"
    NAN          '//     "Not a number"
    ERR          '//     "Error"
    SYM_SCL1     '//     "Choose current base point"
    SYM_SCL2     '//     "Choose current reference point"
    SYM_SCL3     '//     "Choose new base point"
    SYM_SCL4     '//     "Choose new reference point"
    SAME         '//     "Same"
    SYM_EDEL     '//     "The block definition is no longer present"
    ASKQ         '//     "Tell me ..."
    SYM_EPRES    '//     "Block definition is already present in current drawing." 
    SYM_HAS      '//     "Block definition is present in current drawing. Owerwrite?" 
    SYM_DEFIMP   '//     "Definition was imported"
    NEXTPOINT    '//     "Next point"
    NOSELLI      '//     "No selection in list"
    SLOPETLZ     '//     "Slope"
    LENGHT       '//     "Lenght"
    SY_SELLIMP   '//     "Select limiting polyline"
    FIXLEN       '//     "Fixed lenght"
    ERR_EXCEPT   '//     "Error caused by exception...."
    IMGADDED     '//     "The image was added to database"
    IMGFLD_IMPOK '//     "A number of {0:d} images were imported"
    POLYPTS      '//     "Polyline points"
    PTS_WITHNR   '//     "With numbers. First point is:"
    PTS_RSTPOS   '//     "Reset attribute's position to default"
    PTS_RSTUNM   '//     "Reset only those that were not moved"
    PTS_NORST    '//     "Don't reset position"
    PTS_RSTSMART '//     "Smart reset"
    DELORIGPOLY  '//     "Delete original polyline"
    CREATEPLYLFT '//     "Create polyline for leftover"
    GENERAL      '//     "General"
    HFROMPICK    '//     "Height from pick"
    HUSETHIS     '//     "Use this height"
    CREATE       '//     "Create"
    SAVE         '//     "Save"
    PT3D_ERPRS   '//     "The line could not be interpreted..."
    ADDOBJTOSEL  '//     "Add objects to selection"
    REMOBJTOSEL  '//     "Remove objects from selection"
    ERRP_ID1     '//     "Point is identical to first point"
    ERRP_ID2     '//     "Point is identical to second point"
    ALOWNQPT     '//     "Alow non-unique points"
    ADDPT_EXST   '//     "Point already in list"
    ADDPT_INF    '//     "Picked point is {0} N: {1:n3} E: {2:n3} H: {3:n3}"
    TABLES       '//     "Tables"
    EXCFILES     '//     "Excel files"
    TXTFILES     '//     "Text files"
    XMLFILES     '//     "XML files"
    ALLFILES     '//     "All files"
    ASKERRWRKB   '//     "Specified workbook could not be opened. Retry?"
    ERRWRKS      '//     "That sheet does not exist in workbook. List of sheets:"
    ERRSHLST     '//     "The list of sheets could not be retrived"
    SHTNAME      '//     "Sheet name"
    ROWSTART     '//     "First row"
    COLSTART     '//     "First column"
    ROWCNT       '//     "Rows count"
    COLCNT       '//     "Columns count"
    ERRLAY       '//     "Layout could not be retrived"
    IMPTLAY      '//     "Import table layout"
    CH_TABLAY    '//     "Choose the source file"
    CH_SRCSH     '//     "Choose source sheet"
    CH_SRCLOCSZ  '//     "Source location and size"
    FINSZ        '//     "Final size"
    ADOPTS       '//     "Aditional options"
    SELLOC       '//     "Select location"
    FIT_H        '//     "Fit horizontally"
    FIT_V        '//     "Fit vertically"
    ROWS         '//     "Rows"
    COLS         '//     "Columns"
    START        '//     "Start"
    COUNT        '//     "Count"
    BROWSE       '//     "Browse"
    REFRESH      '//     "Refresh"
    TOTTBLW      '//     "Total table width"
    TOTTBLH      '//     "Total table height"
    CRTBLLAY     '//     "Create table from Excel"
    CRTBLLAYG    '//     "Create table from Excel with GUI"
    SELBPOLY     '//     "Select base polyline"
    SETCUTPOLY   '//     "Select cutting polyline"
    DIMONPOLY    '//     "Dimensions on polyline"
    CURRENT      '//     "Current"
    TEMPLATE     '//     "Template"
    OTHERS       '//     "Others"
    COORDFORM    '//     "Coordinates format"
    IMPTXTOO     '//     "Import text, too"
    DIST         '//     "Distance"
    ONINTERV     '//     "Points on regular intervals"
    PARTS        '//     "Number of parts"
    ANG_P_RAD    '//     "Angle (radians)"
    ANG_P_360    '//     "Angle (360)"
    ANG_P_400    '//     "Angle (400)"
    DELTA_EAST   '//     "d East"
    DELTA_NORTH  '//     "d North"
    DELTA_ELEV   '//     "d Elevation"
    DIST_2D      '//     "2D distance"
    DIST_3D      '//     "3D distance"
    ERRNODOC     '//     "No document is opened"
    UPDATE       '//     "Update"
    UNINSTAL     '//     "Uninstal"
    AUTORUNMSG   '//     "Run at application start-up"
    UNINSTFSK    '//     "Uninstaling FSK..."
    UNINSTMSG    '//     "This dialog allows you to completly remove..."
    FAV    '//     "Favorites"
    FAV_INF    '//     "This dialog allows you to edit the list of ..."
    IMDB_EMINI    '//     "Failed to add favorite. The index ({0}) is smaller than minimum accepted"
    IMDB_EMAXI    '//     "Failed to add favorite. The index ({0}) is larger than maximum accepted"
    IMDB_EGETD    '//     "Failed to add favorite. Internal error while retrieving cells data"
    IMDB_ERRPRES    '//     "The image at this index is already in the list"
    IMDB_ERRNOFAV    '//     "No favorite images defined..."
    IMDB_INXREF    '//     "Image in XRef list"
    IMDB_INSRT    '//     "Image inserted"
    IMDB_DIMSCL    '//     "Dimension scale"
    DIM_ADDSTY      '//      "Add style"
    DIM_ADDDIM      '//      "Add dim."
    DIM_RENM      '//      "Rename"
    SRV_TIP      '//      "Survey module; usefull for postprocessing"
    POLY_TIP      '//      "Tools for polyline manipulation"
    SURVEY1      '//      "Survey - Module 1"
    ESEL_PTOPLINE      '//      "The point must not be part of the polyline"
    PLY_SELOBJINS      '//      "Select objects inside polyline"
    PLY_ROUND      '//      "Make polyline rounder"
    PLY_SHARP      '//      "Make polyline sharper"
    PLY_DELP      '//      "Delete polyline vertex"
    PLY_INSP      '//      "Insert point in polyline"
    PLY_INSMP      '//      "Insert multiple points in polyline"
    SELDIMALGN  '//     "Select aligned dimension"
    CODE      '//     "Code"


End Enum

Public Structure FSK_PT
    Dim i As Integer
    Dim N_1 As Double
    Dim E_1 As Double
End Structure

'// --------------------------------------------------------------------- '
'// describes a 3D point
Public Structure FSK_PT3D
    Dim Name As String
    Dim Descr As String

    Dim North As Double
    Dim East As Double
    Dim Height As Double
End Structure
'// ===================================================================== '


Public Structure FSK_LINE
    Dim N_1 As Double
    Dim E_1 As Double
    Dim N_2 As Double
    Dim E_2 As Double

    Dim bVert As Boolean
    Dim b As Double
    Dim m As Double
End Structure

Public Structure FSK_RECT
    Dim N_1 As Double
    Dim E_1 As Double
    Dim N_2 As Double
    Dim E_2 As Double
End Structure


Public Structure PtMg
    Dim pt() As FSK_PT
    Dim iAlc As Integer
    Dim iUsd As Integer
End Structure

Public Structure PtMg3D
    Dim pt() As FSK_PT3D
    Dim iAlc As Integer
    Dim iUsd As Integer
End Structure

Public Structure LnMg
    Dim ln() As FSK_LINE
    Dim iAlc As Integer
    Dim iUsd As Integer
End Structure


'//  DEFINITIONS    ========================================================= '
'//
'//
'//
'//
'//  DATA    ---------------------------------------------------------------- '


'//  DATA    ================================================================ '
'//
'//
'//
'//
'//  CLASS    --------------------------------------------------------------- '
Public Class CMain

    '// --------------------------------------------------------------------- '
    '// DATA
    Public Const APPSTG As String = "Misc\AppSettings.ini"
    Public Const APPLOG As String = "Misc\App.log"
    Public Const DESCRKEY As String = "Description_"

    '// types of alerts in case of error
    Public Enum ALERTTY
        MSGB '// user is informed via a message box
        PROMPT '// user is informed at command prompt
    End Enum

    '// current alert type in case of error
    Public Shared bAlertType As ALERTTY


    '// types of information
    Public Enum INFORMTY
        MSGB '// user is informed via a message box
        PROMPT '// user is informed at command prompt
    End Enum

    '// current alert type in case of error
    Public Shared bInformType As INFORMTY

    '// languages that code knows
    Public Enum ELANG
        EN '// english
        RO '// romanian
    End Enum

    '// current language
    Public Shared eAppLang As ELANG = ELANG.RO

    '// debug modes
    Public Enum EDEBUG
        NONE = 0
        DBGPRINT
        LOG
        PROMPT
        LOGPROMPT
    End Enum

    '// current language
    Public Shared eAppDbg As EDEBUG = EDEBUG.PROMPT



    '// lists strings in TX in english
    Public Shared sTxTbl_EN() As String = New String() { _
            "English", _
            "OK", _
            "Cancel", _
            "Exception in ", _
            "Utility for grid creation", _
            "No description is provided for this application", _
            "(unnamed)", _
            "Current settings for ", _
            "Cross", _
            "Border", _
            "Values", _
            "Text height", _
            "Line height", _
            "Span", _
            "Model", _
            "Paper", _
            "Options", _
            "Settings", _
            "Current settings conclude to a number of {0:d} elements" & vbCrLf & _
              "Maximum limit is {1:d}", _
            "Non WCS aligned VP.", _
            "Operation aborted.", _
            "Yes", _
            "No", _
            "Distance between", _
            "Markers", _
            "Marker size", _
            "Labels", _
            "Label size", _
            "First point", _
            "Second point", _
            "Third point", _
            "Command not implemented yet", _
            "Select viewport", _
            "Unexpected object type", _
            "Points are too close to each other", _
            "3D points manager", _
            "Symbols manager", _
            "Image database", _
            "Polyline area tools", _
            "Dimensions", _
            "The file does not exist", _
            "Import", _
            "Export", _
            "Name", _
            "Type", _
            "Modified", _
            "Folder", _
            "A decimal separator must be specified", _
            "At least one field separator must be specified", _
            "Decimal separator", _
            "Field separators", _
            "Space", _
            "North", _
            "East", _
            "Height", _
            "Description", _
            "Text field is empty", _
            "This separator is already present in the list", _
            "Content", _
            "Add", _
            "Remove", _
            "Warning", _
            "The settings changed above are not saved!. Change them here", _
            "Last imported", _
            "Last exported", _
            "The text is not the path to a file or folder", _
            "Line", _
            "Word", _
            "Error in file content", _
            "At least a North and an East must be specified", _
            "Point number", _
            "A number of {0:d} points were imported", _
            "Layer for:", _
            "Marker", _
            "Create block", _
            "Block name", _
            "Inappropriate block", _
            "Block", _
            "Separators", _
            "Text", _
            "Format", _
            "Layers", _
            "Ignore errors", _
            "Create entities", _
            "Style", _
            "Error while creating the point", _
            "{0:d} points had errors", _
            "Value is not numeric", _
            "Error writing to file", _
            "No point in current selection. Scanning entire file...", _
            "Active drawing does not contain target block ({0})", _
            "A number of {0:d} points were exported", _
            "A number of {0:d} points were exploded", _
            "A number of {0:d} points were edited", _
            "Explode", _
            "Edit", _
            "Point", _
            "Polyline", _
            "Contour", _
            "Redisplay", _
            "Add image", _
            "Add folder", _
            "Show database", _
            "Database path", _
            "Pick point", _
            "File", _
            "Path", _
            "Scale", _
            "Rotation", _
            "Could not start database", _
            "Database is empty", _
            "No images were found at that location", _
            "Could not retrive database object", _
            "Could not create image dictionary", _
            "No images in cache", _
            "Database editor could not be started", _
            "Select Polyline", _
            "Only Polyline objects are allowed", _
            "Raster image search in progress...", _
            "Select raster image", _
            "Only raster image objects are allowed", _
            "Image found in database. Updating...", _
            "Image was found on another path:" & vbNewLine & _
                "{0}" & vbNewLine & "Owerwrite?", _
            "Select the path to use", _
            "Create marker", _
            "Create text", _
            "Inside", _
            "Database", _
            "View", _
            "Choose", _
            "Select polyline to modify", _
            "Pick point on a side", _
            "Point must not be part of the line", _
            "Polyline must have at least 3 points", _
            "The area is too small", _
            "Requested area is larger than the area of polyline ({0})", _
            "Target area", _
            "By direction", _
            "By fixed point", _
            "Offset", _
            "Move one point", _
            "Offset range", _
            "Area was found after {0} iterations", _
            "Area was not found after {0} iterations", _
            "Maximum number of iterations", _
            "List", _
            "List of areas to construct", _
            "Input", _
            "Output", _
            "Ask for directions after each step", _
            "Area", _
            "Error in", _
            "Skip", _
            "Area list could not be parsed", _
            "A = {0} mp", _
            "Point must be part of the polyline", _
            "Pick point to move", _
            "Previous", _
            "Requested area too small", _
            "Polyline may consist only of lines", _
            "Object intersects itself at offset {0}", _
            "Object intersects itself", _
            "Operation resulted in an unforeseen result", _
            "Pick base point", _
            "Pick point near the side to consider", _
            "Grid in model", _
            "Grid in paper", _
            "Pick", _
            "Could not retrive image info at row {0}", _
            "Maximum grid objects", _
            "{0} elements on border", _
            "{0} elements inside", _
            "Insert", _
            "Insert all symbols", _
            "Symbols per line", _
            "All", _
            "No point is visible in selected area", _
            "Grid", _
            "Close", _
            "General Settings", _
            "Modules", _
            "Version", _
            "Tip", _
            "(no selection)", _
            "Language", _
            "Debug mode", _
            "Alert user", _
            "Inform user", _
            "Use prompt", _
            "Use popup", _
            "(none)", _
            "Debug Output", _
            "Log", _
            "Prompt", _
            "Log and Prompt", _
            "Select file", _
            "Progress", _
            "3D points", _
            "Dimensions", _
            "Image database", _
            "Search results", _
            "Polyline area", _
            "Symbols", _
            "List of symbols", _
            "Source", _
            "Properties", _
            "Commands", _
            "Import definition", _
            "Place one", _
            "On polyline", _
            "On direction", _
            "Not a number", _
            "Error", _
            "Choose current base point", _
            "Choose current reference point", _
            "Choose new base point", _
            "Choose new reference point", _
            "Same", _
            "The block definition is no longer present", _
            "Tell me ...", _
            "Block definition is already present in current drawing.", _
            "Block definition is present in current drawing." & vbNewLine & _
                "Owerwrite?", _
            "Definition was imported", _
            "Next point", _
            "No selection in list", _
            "Slope", _
            "Lenght", _
            "Select limiting polyline", _
            "Fixed lenght", _
            "Exception! Aditional informations provided in Command && Output window.", _
            "The image was added to database", _
            "A number of {0:d} images were imported", _
            "Polyline points", _
            "With numbers. First point is:", _
            "Reset attribute's position to default", _
            "Reset only those that were not moved", _
            "Don't reset position", _
            "Smart reset", _
            "Delete original polyline", _
            "Create polyline for leftover", _
            "General", _
            "Height from pick", _
            "Use this height:", _
            "Create", _
            "Save", _
            "The line could not be interpreted." & vbNewLine & _
                "The format of the line must be:" & vbNewLine & _
                "Name<TAB>North<TAB>East<TAB>Height" & vbNewLine & _
                "or" & vbNewLine & _
                "North<TAB>East<TAB>Height", _
            "Add objects to selection", _
            "Remove objects from selection", _
            "Point is identical to first point", _
            "Point is identical to second point", _
            "Alow non-unique points", _
            "Point already in list", _
            "Picked point is {0} N: {1:n3} E: {2:n3} H: {3:n3}", _
            "Tables", _
            "Excel files", _
            "Text files", _
            "XML files", _
            "All files", _
            "Specified workbook could not be opened." & vbNewLine & "Retry?", _
            "That sheet does not exist in workbook." & vbNewLine & "List of sheets:", _
            "The list of sheets could not be retrived", _
            "Sheet name", _
            "First row", _
            "First column", _
            "Rows count", _
            "Columns count", _
            "Layout could not be retrived", _
            "Import table layout", _
            "Choose the source file", _
            "Choose source sheet", _
            "Source location and size", _
            "Final size", _
            "Aditional options", _
            "Select location", _
            "Fit horizontally", _
            "Fit vertically", _
            "Rows", _
            "Columns", _
            "Start", _
            "Count", _
            "Browse", _
            "Refresh", _
            "Total table width", _
            "Total table height", _
            "Create table from Excel", _
            "Create table from Excel with GUI", _
            "Select base polyline", _
            "Select cutting polyline", _
            "Dimensions on polyline", _
            "Current", _
            "Template", _
            "Others", _
            "Coordinates format", _
            "Import text, too", _
            "Distance", _
            "Points on regular intervals", _
            "Number of parts", _
            "Angle (radians)", _
            "Angle (360)", _
            "Angle (400)", _
            "d East", _
            "d North", _
            "d Elevation", _
            "2D distance", _
            "3D distance", _
            "No document is opened", _
            "Update!", _
            "Uninstal", _
            "Run at application start-up", _
            "Uninstaling FSK...", _
            "    This dialog allows you to completly remove " & _
                "Field Survey Kit from your system." & vbNewLine & _
                "    Warning!!! You should restart Autocad as soon as " & _
                "you uninstal the program to avoid a crash" & vbNewLine & _
                "    The program will be removed completly from your " & _
                "registry and all custom settings will be lost. Also, the " & _
                "content of instalation folder ({0}) will be cleared, except " & _
                "for loaded elements (FSK.dll, for example) that can't " & _
                "deleted at this time. Please remove them manually." & vbNewLine & _
                vbNewLine & _
                "Hopefully, you had a pleasant experience with FSK. " & _
                "Feel free to write an e-mail at nicu.tofan@gmail.com to " & _
                "tell me all about it.", _
            "Favorites", _
            "This dialog allows you to edit the list of files that may be " & _
                "fast loaded in a drawing. Just type the row number of the " & _
                "entry to add, and press <Add>. The entry (if valid) will be " & _
                "added to the list", _
            "Failed to add favorite. The index ({0}) is smaller " & _
                "than minimum accepted ({1})", _
            "Failed to add favorite. The index ({0}) is larger " & _
                "than maximum accepted ({1})", _
            "Failed to add favorite. Internal error while retrieving cells data", _
            "The image at this index is already in the list", _
            "No favorite images defined." & vbNewLine & _
                "Use settings dialog to add images.", _
            "Image in XRef list", _
            "Image inserted", _
            "Dimension scale", _
            "Add style", _
            "Add dim.", _
            "Rename", _
            "Survey module; usefull for postprocessing", _
            "Tools for polyline manipulation", _
            "Survey - Module 1", _
            "The point must not be part of the polyline", _
            "Select objects inside polyline", _
            "Make polyline rounder", _
            "Make polyline sharper", _
            "Delete polyline vertex", _
            "Insert point in polyline", _
            "Insert multiple points in polyline", _
            "Select aligned dimension", _
            "Code", _
            "", _
            "", _
            "", _
            "", _
            ""}



    '// lists strings in TX in romanian
    Public Shared sTxTbl_RO() As String = New String() { _
            "Romana", _
            "OK", _
            "Renunt", _
            "Exceptie in ", _
            "Utilitare pentru crearea gridurilor", _
            "Aceasta aplicatie nu are o descriere", _
            "(fara nume)", _
            "Setari curente pentru ", _
            "Cruce", _
            "Margine", _
            "Valori", _
            "Inaltime text", _
            "Marime linie", _
            "Ecartament", _
            "Model", _
            "Foaie", _
            "Optiuni", _
            "Setari", _
            "Setarile curente genereaza un numar de {0:d} elemente" & vbCrLf & _
              "Limita admisibila este {1:d}", _
            "Viewport-ul nu e aliniat cu coordonatele principale.", _
            "Operatiunea a fost anulata.", _
            "Da", _
            "Nu", _
            "Distanta intre", _
            "Marcatori", _
            "Marimea marcatorului", _
            "Texte", _
            "Marimea textului", _
            "Primul punct", _
            "Al doilea punct", _
            "Al treilea punct", _
            "Comanda nu e implementata", _
            "Selectati viewport-ul", _
            "Tipul obiectului e gresit", _
            "Punctele alese sunt prea apropiate", _
            "Editare puncte 3D", _
            "Editare simboluri", _
            "Imagini raster", _
            "Modificari ale ariei poliliniei", _
            "Dimensiuni", _
            "Fisierul nu exista", _
            "Importa", _
            "Exporta", _
            "Nume", _
            "Tip", _
            "Modificat", _
            "Director", _
            "Separatorul de zecimale lipseste", _
            "Cel putin un separator de campuri trebuie specificat", _
            "Separator pt. zecimale", _
            "Separatori de camp", _
            "Spatiu", _
            "Nord", _
            "Est", _
            "Altitudine", _
            "Descriere", _
            "Casuta-text este goala", _
            "Acest separator e deja in lista", _
            "Continut", _
            "Adauga", _
            "Sterge", _
            "Atentie", _
            "Modificarile aduse mai sus setarilor nu sunt salvate! Modificati de aici", _
            "Ultimul importat", _
            "Ultimul exportat", _
            "Textul nu reprezinta calea catre un fisier sau director", _
            "Linia", _
            "Cuvantul", _
            "Eroare in continutul fisierului", _
            "Valorile pentru Nord si Est nu sunt specificate", _
            "Numar punct", _
            "Un numar de {0:d} puncte au fost importate", _
            "Strat pentru:", _
            "Marcator", _
            "Creez bloc", _
            "Numele blocului", _
            "Bloc nepotrivit", _
            "Bloc", _
            "Separatori", _
            "Text", _
            "Format", _
            "Straturi", _
            "Ignora erorile", _
            "Creaza entitati", _
            "Stil", _
            "Eroare la crearea punctului", _
            "{0:d} puncte cu erori", _
            "Valoarea nu este numerica", _
            "Eroare la scrierea fisierului", _
            "Nici un punct in selectia curenta; se scaneaza intreg desenul...", _
            "Desenul curent nu contine blocul tinta ({0})", _
            "Un numar de {0:d} puncte au fost exportate", _
            "Un numar de {0:d} puncte au fost descompuse (explodate)", _
            "Un numar de {0:d} puncte au fost editate", _
            "Descompune", _
            "Editeaza", _
            "Punct", _
            "Polilinie", _
            "Contur", _
            "Reafiseaza", _
            "Adauga imagine", _
            "Adauga folder", _
            "Afiseaza baza de date", _
            "Calea catre baza de date", _
            "Alegeti punctul", _
            "Fisier", _
            "Calea", _
            "Scara", _
            "Rotatia", _
            "Baza de date nu a putut fi deschisa", _
            "Baza de date este goala", _
            "Nici o imagine la locatia solicitata", _
            "Nu pot crea dictionar pentru imagini", _
            "Baza de date nu a raspuns solicitarii", _
            "Nici o cautare stocata", _
            "Editorul pentru baz de date nu a putut fi pornit", _
            "Seletati polilinia", _
            "Doar poliliniile sunt admise", _
            "Cautare imagini-raster in curs...", _
            "Seletati imaginea", _
            "Doar imaginile sunt admise", _
            "Imaginea a fost gasita in baza de date. Se modifica...", _
            "Imaginea a fost gasita la o alta adresa:" & vbNewLine & _
                "{0}" & vbNewLine & "Suprascriem?", _
            "Selectati calea de urmat", _
            "Creaza marker", _
            "Creaza text", _
            "In interior", _
            "Baza de date", _
            "Vezi", _
            "Alege", _
            "Selectati polilinia de parcelat", _
            "Alegeti un punct de o parte sau de alta", _
            "Punctul nu poate face parte din linie", _
            "Polilinia trebuie sa aiba minim 3 puncte", _
            "Aria este prea mica", _
            "Aria ceruta e mai mare decat aria poliliniei ({0})", _
            "Aria tinta", _
            "Dupa directie", _
            "Cu punct obligat", _
            "Ofset", _
            "Muta un punct", _
            "Muta puncte", _
            "Aria a fost gasita dupa {0} iteratii", _
            "Aria nu a fost gasita dupa {0} iteratii", _
            "Numarul maxim de iteratii", _
            "List", _
            "Lista suprafetelor de construit", _
            "Date de intrare", _
            "Date de iesire", _
            "Cere directia dupa fiecare pas", _
            "Aria", _
            "Eroare in", _
            "Ignora", _
            "Lista de suprafete nu a fost inteleasa", _
            "S = {0} mp", _
            "Punctul trebuie sa fie parte a poliliniei", _
            "Alegeti punctul de modificat", _
            "Stocata", _
            "Aria solicitata e prea mica", _
            "Polilinia trebuie sa fie formata doar din linii", _
            "Obiectul se intersecteaza cu el insusi la offset = {0}", _
            "Obiectul se intersecteaza cu el insusi", _
            "Operatiunea a avut un rezultat neprevazut", _
            "Alegeti punctul obligat", _
            "Alegeti partea ce trebuie adusa in supfatata", _
            "Caroiaj in model", _
            "Caroiaj in foaie", _
            "Alege", _
            "Imaginea de pe randul {0} nu a putut fi descifrata", _
            "Numar maxim de marcatori", _
            "Elemente generate pe margine: {0}", _
            "Elemente generate in interior: {0}", _
            "Inserare", _
            "Insereaza toate simbolurile", _
            "Numar de simboluri pe linie", _
            "Toate", _
            "Nici un punct nu e vizibil in conturul selectat", _
            "Caroiaj", _
            "Inchide", _
            "Setari globale", _
            "Module", _
            "Versiunea", _
            "Indiciu", _
            "(nici o selectie)", _
            "Limba", _
            "Mod depanare", _
            "Mesaj de eroare", _
            "Informatii", _
            "Cu prompt", _
            "Cu mesaj", _
            "(nici unul)", _
            "Debug Output", _
            "In fisier", _
            "Prompt", _
            "In fisier si Prompt", _
            "Selectati fisierul", _
            "Progres", _
            "Puncte 3D", _
            "Dimensiuni", _
            "Baza de date pentru imagini", _
            "Rezultatele cautarii", _
            "Aria poliliniei", _
            "Simboluri", _
            "Lista de simboluri", _
            "Sursa", _
            "Proprietati", _
            "Comenzi", _
            "Importa definitia", _
            "Adauga unul", _
            "Pe polilinie", _
            "Pe linie", _
            "Textul nu reprezinta un numar", _
            "Eroare", _
            "Alegeti punctul curent", _
            "Alegeti referinta curenta", _
            "Alegeti punctul nou", _
            "Alegeti referinta noua", _
            "Identic", _
            "Definitia blocului nu mai fost gasita", _
            "Spune-mi ...", _
            "Definitia blocului e deja prezenta in desenul curent", _
            "Definitia blocului e prezenta in desenul curent." & vbNewLine & _
                "Suprascriem?", _
            "Definitia blocului a fost importata", _
            "Urmatorul punct", _
            "Nici un element selectat in lista", _
            "Taluz", _
            "Lungimea", _
            "Selectati polilinia de delimitare", _
            "Lungime constanta", _
            "Exceptie! Pentru mai multe informatii consultati fereastra de comanda si informatii.", _
            "Imaginea a fost adaugata in baza de date", _
            "Un numar de {0:d} imagini au fost importate", _
            "Puncte pe polilinie", _
            "Cu numar. Primul punct este:", _
            "Reseteaza pozitia atributelor la locatia implicita", _
            "Reseteaza doar cele aflate in pozitia originala", _
            "Nu reseta pozitia", _
            "Resetare diferentiata (lasa-te pe mana mea)", _
            "Sterge polilinia initiala", _
            "Creaza polilinie pentru rest", _
            "General", _
            "Determina automat altitudinea", _
            "Foloseste altitudinea:", _
            "Creaza", _
            "Salveaza", _
            "Linia nu a putut fi interpretata." & vbNewLine & _
                "Formatul liniei trebuie sa fie:" & vbNewLine & _
                "Nume<TAB>Nord<TAB>Est<TAB>Altitudine" & vbNewLine & _
                "sau" & vbNewLine & _
                "Nord<TAB>Est<TAB>Altitudine", _
            "Adaugati elemente la selectia curenta", _
            "Stergeti elemente din selectia curenta", _
            "Punctul ales e acelasi cu primul punct", _
            "Punctul ales e acelasi cu al doilea punct", _
            "Permite puncte dublate", _
            "Punctul e deja prezent in lista", _
            "Punctul ales este {0} N: {1:n3} E: {2:n3} H: {3:n3}", _
            "Tabel", _
            "Fisiere Excel", _
            "Fisiere text", _
            "Fisiere XML", _
            "Toate fisierele", _
            "Fisierul specificat nu a putut fi deschis. Reincercam?", _
            "Aceasta foaie nu exista in fisier." & vbNewLine & "Lista foilor:", _
            "Lista foilor nu a putut fi obtinuta din fisier", _
            "Numele foii", _
            "Primul rand", _
            "Prima coloana", _
            "Numarul de randuri", _
            "Numarul de coloane", _
            "Forma tabelului nu a putut fi extrasa", _
            "Importa sablon de tabel din Excel", _
            "Selectati fisierul sursa", _
            "Selectati foaia sursa", _
            "Locatia si dimensiunile", _
            "Dimensiune finala", _
            "Alte optiuni", _
            "Selectati locatia", _
            "pe orizontala", _
            "pe verticala", _
            "Randuri", _
            "Coloane", _
            "Inceput", _
            "Numar", _
            "Alege", _
            "Refresh", _
            "Latime totala tabel", _
            "Inaltime totala tabel", _
            "Selectati polilinia-baza", _
            "Creare tabel din Excel", _
            "Creare tabel din Excel cu interfata", _
            "Selectati polilinia de taiere", _
            "Dimensiuni pe polilinie", _
            "Curent", _
            "Sablon", _
            "Altele", _
            "Formatul coordonatelor", _
            "Importa si textul", _
            "Distanta", _
            "Puncte la intervale egale", _
            "Numar de parti", _
            "Unghi (radiani)", _
            "Unghi (360)", _
            "Unghi (400)", _
            "d Est", _
            "d Nord", _
            "d Altitudine", _
            "Distanta 2D", _
            "Distanta 3D", _
            "Nici un document deschis", _
            "Actualizare", _
            "Dezinstalare", _
            "Porneste cand se initializeaza Autocad-ul", _
            "Dezinstalare FSK...", _
            "    Aceasta fereastra va permite sa dezinstalati " & _
                "Field Survey Kit, eliminand elementele asociate." & vbNewLine & _
                "    Atentie!!! Autocad-ul trebuie restartat imediat dupa " & _
                "dezinstalare, deoarece componentele lipsa pot provoca " & _
                "probleme grave." & vbNewLine & _
                "    Programul va fi sters din registrii, " & _
                "toate setarile particularizate fiind pierdute. Continutul " & _
                "directorului unde a fost instalat ({0}) wa fi sters, exceptand " & _
                "elementele incarcate in memorie (FSK.dll, de exemplu) care " & _
                "nu pot fi sterse de acest program." & vbNewLine & _
                vbNewLine & _
                "Sper ca programul nu va lasa un gust amar. :) " & _
                "Daca simtiti nevoia de a-mi impartasi experienta, " & _
                "astept mail-uri la adresa nicu.tofan@gmail.com.", _
            "Favorite", _
            "Aceasta fereastra va permite sa editati imaginile ce pot " & _
                "fi inserate rapid folosind butonul din bara de unelte. " & _
                "Trebuie doar sa inserati numarul randului (!) pe care " & _
                "se afla imaginea in baza de date si sa apasati <Adauga>.", _
            "Imaginea favorita nu a fost adaugata. Index-ul furnizat ({0}) este mai mic " & _
                "decat limita minima ({1})", _
            "Imaginea favorita nu a fost adaugata. Index-ul furnizat ({0}) este mai mare " & _
                "decat limita maxima ({1})", _
            "Imaginea favorita nu a fost adaugata. Continutul celulelor nu a putut fi citit.", _
            "Imaginea de la acest index e deja prezenta in lista.", _
            "Nici o imagine nu a fost marcata ca fiind favorita." & vbNewLine & _
                "Folositi fereastra de setari pentru a adauga imagini.", _
            "Imaginea e atasata", _
            "Imaginea e inserata", _
            "Scara dimensiunilor", _
            "Adauga stil", _
            "Adauga dim.", _
            "Redenumeste", _
            "Modul pentru postprocesarea datelor din masuratori", _
            "Unelte pentru ajustarea poliliniilor", _
            "Masuratori - Modului 1", _
            "Punctul nu poate face parte din polilinie", _
            "Selecteaza obiectele din interiorul unei polilinii", _
            "Rotunjeste polilinia", _
            "Ascute polilinia", _
            "Sterge punct din polilinie", _
            "Insereaza punct in polilinie", _
            "Insereaza mai multe puncte in polilinie", _
            "Selectati dimensiunea", _
            "Cod", _
            "", _
            "", _
            "", _
            "" _
            }


    '// ===================================================================== '

    '// used in near-exact computations
    Public Const MARGIN As Double = 0.0001
    '// will be changed each time an update should be tiggered
    Public Const INTERNAL_VERSION As Long = 100

    <System.Security.SuppressUnmanagedCodeSecurity()> _
    <DllImport("acad.exe", CharSet:=CharSet.Auto, CallingConvention:=CallingConvention.Cdecl)> _
    Friend Shared Function acedGetEnv(ByVal envName As String, ByVal ReturnValue As String) As Integer
    End Function

    <System.Security.SuppressUnmanagedCodeSecurity()> _
    <DllImport("acad.exe", CharSet:=CharSet.Auto, CallingConvention:=CallingConvention.Cdecl)> _
    Friend Shared Function acedSetEnv(ByVal envName As String, ByVal NewValue As String) As Integer
    End Function


    '// --------------------------------------------------------------------- '
    '// Unified function for getting a string
    Public Shared Function _T(ByVal eS As TX) As String
        If eAppLang = ELANG.RO Then
            Return sTxTbl_RO(eS)
        Else
            Return sTxTbl_EN(eS)
        End If
    End Function
    '// ===================================================================== '


    '// --------------------------------------------------------------------- '
    '// Unified function for alerting the user; a global option may be used
    '// to tell if this alert is a message box or a prompt
    Public Shared Sub AlertUser(ByVal sTxt As String)
        Dim acDoc As Document = Application.DocumentManager.MdiActiveDocument
        If (acDoc Is Nothing) Or (bAlertType = ALERTTY.MSGB) Then
            Autodesk.AutoCAD.ApplicationServices.Application. _
                ShowAlertDialog(sTxt)
        Else
            acDoc.Editor.WriteMessage(sTxt & vbNewLine)
        End If
    End Sub
    Public Shared Sub AlertUser(ByVal eS As TX)
        If eAppLang = ELANG.RO Then
            AlertUser(sTxTbl_RO(eS))
        Else
            AlertUser(sTxTbl_EN(eS))
        End If
    End Sub
    '// ===================================================================== '

    '// --------------------------------------------------------------------- '
    '// Unified function for informing the user; a global option may be used
    '// to tell if this alert is a message box or a prompt
    Public Shared Sub InformUser(ByVal sTxt As String)
        Dim acDoc As Document = Application.DocumentManager.MdiActiveDocument
        If (acDoc Is Nothing) Or (bInformType = INFORMTY.MSGB) Then
            MsgBox(sTxt)
        Else
            acDoc.Editor.WriteMessage(sTxt & vbNewLine)
        End If
    End Sub
    Public Shared Sub InformUser(ByVal eS As TX)
        If eAppLang = ELANG.RO Then
            InformUser(sTxTbl_RO(eS))
        Else
            InformUser(sTxTbl_EN(eS))
        End If
    End Sub
    '// ===================================================================== '

    '// --------------------------------------------------------------------- '
    '// Unified function for informing the user that an exception occured
    '// via a MessageBox
    Public Shared Sub PopUpExc()
        MsgBox(CMain._T(TX.ERR_EXCEPT), _
               MsgBoxStyle.Critical Or MsgBoxStyle.ApplicationModal, _
               CMain._T(TX.ERR))
    End Sub
    '// ===================================================================== '

    '// --------------------------------------------------------------------- '
    '// Unified function for displaying exceptions
    Public Shared Sub DebugException(ByRef ex As System.Exception)
        Try

            Dim trace As System.Diagnostics.StackTrace = _
                      New System.Diagnostics.StackTrace(ex, True)
            Dim exceptionLineNumber As Integer = _
                      trace.GetFrame(0).GetFileLineNumber()

            Dim sOut As String = vbNewLine & _
            "---------------------------------------" & vbNewLine & _
            _T(TX.EXC_IN) & trace.GetFrame(0).GetMethod.Name & vbCrLf & _
       CStr(ex.Message) & "; " & vbCrLf & _
       trace.GetFrame(0).ToString & vbCrLf & _
            "---------------------------------------" & vbNewLine


            '// todo remove following chunk
            Dim acDoc1 As Document = _
                Application.DocumentManager.MdiActiveDocument
            If acDoc1 Is Nothing Then Exit Sub
            acDoc1.Editor.WriteMessage(sOut)

            Select Case CMain.eAppDbg
                Case EDEBUG.DBGPRINT
                    Debug.Print(sOut)
                Case EDEBUG.LOG
                    Dim objWRi As System.IO.StreamWriter = Nothing
                    objWRi = New System.IO.StreamWriter( _
                        CApp.sAppPath & APPLOG, True)
                    objWRi.Write(sOut)
                    objWRi.Close()
                Case EDEBUG.PROMPT
                    Dim acDoc As Document = _
                        Application.DocumentManager.MdiActiveDocument
                    If acDoc Is Nothing Then Exit Sub
                    acDoc.Editor.WriteMessage(sOut)
                Case EDEBUG.LOGPROMPT
                    Dim objWRi As System.IO.StreamWriter = Nothing
                    objWRi = New System.IO.StreamWriter( _
                        CApp.sAppPath & APPLOG, True)
                    objWRi.Write(sOut)
                    objWRi.Close()
                    Dim acDoc As Document = _
                        Application.DocumentManager.MdiActiveDocument
                    If acDoc Is Nothing Then Exit Sub
                    acDoc.Editor.WriteMessage(sOut)
                    'Case EDEBUG.NONE

            End Select

        Catch exc As System.Exception
        End Try
        GC.Collect()
        GC.WaitForPendingFinalizers()
    End Sub
    '// ===================================================================== '

    '// --------------------------------------------------------------------- '
    '// tests if a layer exists or not in a given document
    '// @param Document     - the doc to search
    '// @param sName        - string to search
    '// @return object ID or Nothing
    Public Shared Function Lay_Exists( _
            ByRef acDoc As Document, _
            ByRef sName As String) _
            As ObjectId


        Dim acCurDb As Database = Nothing
        Dim acLyrTbl As LayerTable = Nothing
        Dim sLayerNames As String = ""
        Dim acLyrTblRec As LayerTableRecord
        Dim acObjId As ObjectId = Nothing
        Dim rObjId As ObjectId = Nothing


        Try
            acCurDb = acDoc.Database

            '' Start a transaction
            Using acTrans As Transaction = acCurDb.TransactionManager.StartTransaction()

                '' Open the Layer table for read
                acLyrTbl = DirectCast( _
                    acTrans.GetObject(acCurDb.LayerTableId, OpenMode.ForRead),  _
                    LayerTable)

                For Each acObjId In acLyrTbl
                    acLyrTblRec = DirectCast( _
                        acTrans.GetObject(acObjId, OpenMode.ForRead),  _
                        LayerTableRecord)
                    If acLyrTblRec.Name = sName Then
                        rObjId = acObjId
                        Exit For
                    End If
                Next

                '' Dispose of the transaction
            End Using

        Catch ex As System.Exception
            CMain.DebugException(ex)
        End Try
        Return rObjId

    End Function
    '// ===================================================================== '

    '---------------------------------------------------------------------------------------------'
    '// this will generate a list of tokens baseed on separators' return nr of tokens  '
    '// @param LnIn       - source string                                                           '
    '// @param LnOut      - tokenized output                                                       '
    '// @param SpLst      - string list to be considered as separators                             '
    '// @return number of tokens that were extracted
    Public Shared Function Ln2Tk( _
        ByRef LnIn As String, _
        ByRef LnOut() As String, _
        ByRef SpLst() As String) As Integer

        Dim a As Object
        Dim Sp() As Integer
        Dim i As Integer
        Dim j As Integer
        Dim cSt As Integer
        Dim k As Integer

        If LnIn Is Nothing Then Return 0
        If LnIn.Length = 0 Then Return 0
        Try
            ReDim Sp(0 To UBound(SpLst))
            k = 0
            ReDim LnOut(0 To k)
            LnOut(0) = ""
            i = 0
            cSt = 1
            For Each a In SpLst
                Sp(i) = CInt(InStr(1, LnIn, a.ToString()))
                If (Sp(i) = 0) Then Sp(i) = 10000
                i = i + 1
            Next a
            cSt = 1

            ' find lowest separator
            j = 0
            For i = 1 To UBound(Sp)
                If (Sp(i) < Sp(j)) Then j = i
            Next i
            If (Sp(j) = 10000) Then
                ' no more separators
                GoTo EndOfLn
            End If

            LnOut(k) = Mid(LnIn, cSt, Sp(j) - cSt)

            cSt = Sp(j) + Len(SpLst(j))
            If (LnOut(k) <> "") Then
                k = k + 1
                ReDim Preserve LnOut(0 To k)
                LnOut(k) = ""
            End If

            Sp(j) = InStr(cSt, LnIn, SpLst(j))
            If (Sp(j) = 0) Then Sp(j) = 10000

            Do
                ' find lowest separator
                j = 0
                For i = 1 To UBound(Sp)
                    If (Sp(i) < Sp(j)) Then j = i
                Next i
                If (Sp(j) = 10000) Then
                    ' no more separators
                    GoTo EndOfLn
                End If
                LnOut(k) = Mid(LnIn, cSt, Sp(j) - cSt)
                If (LnOut(k) <> "") Then
                    k = k + 1
                    ReDim Preserve LnOut(0 To k)
                    LnOut(k) = ""
                End If
                cSt = Sp(j) + Len(SpLst(j))


                Sp(j) = InStr(cSt, LnIn, SpLst(j))
                If (Sp(j) = 0) Then Sp(j) = 10000
            Loop

EndOfLn:
            LnOut(k) = Mid(LnIn, cSt, Len(LnIn) - cSt + 1)
            Return k + 1
        Catch ex As System.Exception
            DebugException(ex)
            Return 0
        End Try
        GC.Collect()
        GC.WaitForPendingFinalizers()
    End Function
    '============================================================================================='

    '---------------------------------------------------------------------------------------------'
    '// returns next line from a given string
    Public Shared Function NextLine(ByRef sIn As String, ByRef iLoc As Integer) As String
        Dim sOut As String
        Dim NextStop As Integer = _
        sIn.IndexOf(vbNewLine, iLoc)
        If (NextStop = -1) Then Return Nothing
        sOut = sIn.Substring(iLoc, NextStop - iLoc)
        iLoc = NextStop + vbNewLine.Length
        Return sOut
    End Function
    '============================================================================================='

    '---------------------------------------------------------------------------------------------'
    Public Shared Sub ReleaseComObject(ByVal o As Object)
        ' Credit: Dig-Boy
        'A safe way to explicitly release the resources associated with a COM object that has been called by the application.
        ' Without this call the resource will persist on the user's system as a running process that is unaccessible until it
        ' is killed in Task Manager or the computer is shut down.  Note that this is a two step process of first releasing 
        ' then setting the object to nothing.  DO NOT SET THE OBJECT TO NOTHING BEFORE RUNNING THIS METHOD.  Also, always 
        ' close down the object through its proper library methods before running this function (i.e. close documents/spreadsheets
        ' and Quit the Word/Excel app then run each of these objects through this function.
        Try
            System.Runtime.InteropServices.Marshal.FinalReleaseComObject(o)
        Catch
            'Usually because the object is Nothing or has already been released...  Ignore.
        Finally
            If o IsNot Nothing Then o = Nothing
        End Try
    End Sub
    '============================================================================================='

    '---------------------------------------------------------------------------------------------'
    '// Checks if a line segment is inside or intersects a given rectangle
    '// returns either FALSE if the two linews are paralel or TRUE if they intersect
    '// @param Ln1       - line that should be intersected                                                         '
    '// @param Ln2       - line that should be intersected                                                         '
    '// @param i1        - result on first line                                                       '
    '// @param i2        - result on second line
    '// @param pt        - resulted point
    Public Const iONFIRST As Integer = 1
    Public Const iONSECOND As Integer = 2
    Public Const iINSIDE As Integer = 3
    Public Const iOUTSIDE As Integer = 0

    Public Shared Function Intersect_LnLn( _
        ByRef Ln1 As FSK_LINE, _
        ByRef Ln2 As FSK_LINE, _
        ByRef pt As FSK_PT, _
        ByRef i1 As Integer, _
        ByRef i2 As Integer _
        ) As Boolean

        If (Ln1.bVert) Then
            '// first line is vertical
            If Ln2.bVert Then
                Return False
            End If
            '// not paralel
            pt.E_1 = Ln1.E_1
            pt.N_1 = pt.E_1 * Ln2.m + Ln2.b

        ElseIf Ln2.bVert = True Then
            '// second line is vertical (first is not vertical)
            pt.E_1 = Ln2.E_1
            pt.N_1 = pt.E_1 * Ln1.m + Ln1.b

        ElseIf Math.Abs(Ln1.m - Ln2.m) < CMain.MARGIN Then
            '// not vertical but paralel
            Return False
        Else
            '// no vertical and not paralel
            pt.E_1 = -1 * (Ln2.b - Ln1.b) / (Ln2.m - Ln1.m)
            pt.N_1 = pt.E_1 * Ln1.m + Ln1.b

        End If

        '// intersection point has been computed

        '// check if is part of first line
        Dim dEDif1 As Double, dNDif1 As Double
        Dim dEDif2 As Double, dNDif2 As Double


        dEDif1 = Ln1.E_1 - pt.E_1
        dEDif2 = Ln1.E_2 - pt.E_1
        dNDif1 = Ln1.N_1 - pt.N_1
        dNDif2 = Ln1.N_2 - pt.N_1

        If Math.Abs(dEDif1) < CMain.MARGIN AndAlso _
            Math.Abs(dNDif1) < CMain.MARGIN Then
            '// first point was hit
            i1 = iONFIRST
        ElseIf Math.Abs(dEDif2) < CMain.MARGIN AndAlso _
            Math.Abs(dNDif2) < CMain.MARGIN Then
            '// second point was hit
            i1 = iONSECOND
        ElseIf dEDif1 * dEDif2 < 0 Then
            '// the point is inside
            i1 = iINSIDE
        Else
            '// the point is outside
            i1 = iOUTSIDE
        End If


        dEDif1 = Ln2.E_1 - pt.E_1
        dEDif2 = Ln2.E_2 - pt.E_1
        dNDif1 = Ln2.N_1 - pt.N_1
        dNDif2 = Ln2.N_2 - pt.N_1

        If Math.Abs(dEDif1) < CMain.MARGIN AndAlso _
            Math.Abs(dNDif1) < CMain.MARGIN Then
            '// first point was hit
            i2 = iONFIRST

        ElseIf Math.Abs(dEDif2) < CMain.MARGIN AndAlso _
            Math.Abs(dNDif2) < CMain.MARGIN Then
            '// second point was hit
            i2 = iONSECOND

        ElseIf dEDif1 * dEDif2 < 0 Then
            '// the point is inside
            i2 = iINSIDE

        Else
            '// the point is outside
            i2 = iOUTSIDE

        End If
        GC.Collect()
        GC.WaitForPendingFinalizers()
        Return True

    End Function
    '============================================================================================='

    '---------------------------------------------------------------------------------------------'
    '// Creates an array of points where a line (not a segment) intersects 
    '// a polyline
    '// @param Ln       - the line that should be intersected                                                         '
    '// @param acPoly   - the polyline to check                                                      '
    '// @param bForceClosure   - if polyline is not closed and this is true
    '//     a line is imaginated from last point to first                                                       '
    Public Shared Sub Intersect_LnPoly( _
        ByRef Ln As FSK_LINE, _
        ByRef acPoly As Polyline, _
        ByVal bForceClosure As Boolean, _
        ByRef pts As PtMg)

        '// bring the array in a known state
        pts.iAlc = 4
        pts.iUsd = 0
        ReDim pts.pt(0 To pts.iAlc - 1)

        Dim LnPl As FSK_LINE
        Dim intPt As FSK_PT
        Dim i1 As Integer, i2 As Integer
        Dim acPt As Point2d
        Dim dDeltaN As Double, dDeltaE As Double
        acPt = acPoly.GetPoint2dAt(0)
        LnPl.N_1 = acPt.Y
        LnPl.E_1 = acPt.X


        For i As Integer = 1 To acPoly.NumberOfVertices - 1
            acPt = acPoly.GetPoint2dAt(i)
            LnPl.N_2 = acPt.Y
            LnPl.E_2 = acPt.X
            dDeltaN = LnPl.N_2 - LnPl.N_1
            dDeltaE = LnPl.E_2 - LnPl.E_1
            If Math.Abs(dDeltaE) < CMain.MARGIN Then
                If Math.Abs(dDeltaN) < CMain.MARGIN Then
                    Continue For
                End If
                LnPl.bVert = True
                LnPl.b = 0
                LnPl.m = 0
            Else
                LnPl.bVert = False
                LnPl.m = dDeltaN / dDeltaE
                LnPl.b = LnPl.N_1 - LnPl.m * LnPl.E_1
            End If
            If Intersect_LnLn(Ln, LnPl, intPt, i1, i2) Then
                '// we have an intersection
                If (i2 = iONFIRST) Or (i2 = iINSIDE) Then
                    AddPtToChain(pts, intPt)
                End If
            End If

            LnPl.N_1 = LnPl.N_2
            LnPl.E_1 = LnPl.E_2
        Next

        If acPoly.Closed = True Or bForceClosure = True Then

            acPt = acPoly.GetPoint2dAt(0)
            LnPl.N_2 = acPt.Y
            LnPl.E_2 = acPt.X
            dDeltaN = LnPl.N_2 - LnPl.N_1
            dDeltaE = LnPl.E_2 - LnPl.E_1
            If Math.Abs(dDeltaE) < CMain.MARGIN Then
                If Math.Abs(dDeltaN) < CMain.MARGIN Then
                    Return
                End If
                LnPl.bVert = True
                LnPl.b = 0
                LnPl.m = 0
            Else
                LnPl.bVert = False
                LnPl.m = dDeltaN / dDeltaE
                LnPl.b = LnPl.N_1 - LnPl.m * LnPl.E_1
            End If
            If Intersect_LnLn(Ln, LnPl, intPt, i1, i2) Then
                '// we have an intersection (not paralel)
                If (i2 = iONFIRST) Or (i2 = iINSIDE) Then
                    '// avoid points outside polyline
                    AddPtToChain(pts, intPt)
                End If
            End If
        End If
        GC.Collect()
        GC.WaitForPendingFinalizers()

    End Sub
    '============================================================================================='

    '// --------------------------------------------------------------------- '
    '// checks a point against a polyline and tells if is outside, a vertex 
    '// or on a line
    Public Enum POLYPT
        OUTSIDE
        VERTEX
        LINE
    End Enum
    Public Shared Function PolyVsPt( _
        ByRef acPoly As Polyline, _
        ByRef pkp As FSK_PT, _
        ByRef iClosestLn As Integer) As POLYPT

        Dim acP1 As Point2d = Nothing
        Dim acP2 As Point2d = Nothing
        Dim pk2 As FSK_PT
        Dim r As Double
        Dim dMin As Double = Double.MaxValue
        Dim iMin As Integer = Integer.MaxValue
        Dim dCrtD As Double

        '// check first point
        acP1 = acPoly.GetPoint2dAt(0)
        If (Math.Abs(acP1.X - pkp.E_1) < CMain.MARGIN) Then
            If (Math.Abs(acP1.X - pkp.E_1) < CMain.MARGIN) Then
                '// this point is part of the polyline
                Return POLYPT.VERTEX
            End If
        End If

        '// iterate i points to see if the pick may be used
        For i As Integer = 1 To acPoly.NumberOfVertices - 1
            acP2 = acPoly.GetPoint2dAt(i)
            If (Math.Abs(acP2.X - pkp.E_1) < CMain.MARGIN) Then
                If (Math.Abs(acP2.X - pkp.E_1) < CMain.MARGIN) Then
                    '// this point is part of the polyline
                    pkp.i = i
                    Return POLYPT.VERTEX
                End If
            End If
            r = ((pkp.E_1 - acP1.X) * (acP2.X - acP1.X) + (pkp.N_1 - acP1.Y) * (acP2.Y - acP1.Y)) / _
                ((acP2.X - acP1.X) * (acP2.X - acP1.X) + (acP2.Y - acP1.Y) * (acP2.Y - acP1.Y))
            If (r > 0) And (r < 1) Then
                pk2.E_1 = acP1.X + r * (acP2.X - acP1.X)
                pk2.N_1 = acP1.Y + r * (acP2.Y - acP1.Y)
                dCrtD = GetLnLen(pkp, pk2)
                If (dCrtD < CMain.MARGIN) Then
                    pkp.i = i - 1
                    Return POLYPT.LINE
                ElseIf dCrtD < dMin Then
                    iMin = i - 1
                    dMin = dCrtD
                End If
            End If
            acP1 = acP2
        Next
        If (acPoly.Closed) Then
            acP2 = acPoly.GetPoint2dAt(0)
            r = ((pkp.E_1 - acP1.X) * (acP2.X - acP1.X) + (pkp.N_1 - acP1.Y) * (acP2.Y - acP1.Y)) / _
                ((acP2.X - acP1.X) * (acP2.X - acP1.X) + (acP2.Y - acP1.Y) * (acP2.Y - acP1.Y))
            If (r > 0) And (r < 1) Then
                pk2.E_1 = acP1.X + r * (acP2.X - acP1.X)
                pk2.N_1 = acP1.Y + r * (acP2.Y - acP1.Y)
                dCrtD = GetLnLen(pkp, pk2)
                If (dCrtD < CMain.MARGIN) Then
                    pkp.i = acPoly.NumberOfVertices - 1
                    Return POLYPT.LINE
                ElseIf dCrtD < dMin Then
                    iMin = acPoly.NumberOfVertices - 1
                    dMin = dCrtD
                End If
            End If
        End If
        iClosestLn = iMin
        Return POLYPT.OUTSIDE
    End Function
    '// ===================================================================== '

    '---------------------------------------------------------------------------------------------'
    '// Checks if a line segment is inside or intersects a given rectangle
    Public Shared Function Intersect_LnRect( _
        ByRef Ln As FSK_LINE, _
        ByRef Rect As FSK_RECT) As Boolean

        Dim dTmp As Double
        If (Rect.N_1 > Rect.N_2) Then
            dTmp = Rect.N_1
            Rect.N_1 = Rect.N_2
            Rect.N_2 = dTmp
        End If
        If (Rect.E_1 > Rect.E_2) Then
            dTmp = Rect.E_1
            Rect.E_1 = Rect.E_2
            Rect.E_2 = dTmp
        End If

        Dim RctLn As FSK_RECT
        If (Ln.N_1 > Ln.N_2) Then
            RctLn.N_1 = Ln.N_2
            RctLn.N_2 = Ln.N_1
        Else
            RctLn.N_1 = Ln.N_1
            RctLn.N_2 = Ln.N_2
        End If
        If (Ln.E_1 > Ln.E_2) Then
            RctLn.E_1 = Ln.E_2
            RctLn.E_2 = Ln.E_1
        Else
            RctLn.E_1 = Ln.E_1
            RctLn.E_2 = Ln.E_2
        End If


        If (RctLn.N_1 > Rect.N_2) Then
            '// Line is Above the rectangle
            Return False
        End If
        If (RctLn.N_2 < Rect.N_1) Then
            '// Line is Below the rectangle
            Return False
        End If
        If (RctLn.E_1 > Rect.E_2) Then
            '// Line is To the right
            Return False
        End If
        If (RctLn.E_2 < Rect.E_1) Then
            '// Line is To the left
            Return False
        End If

        '// rule out horizontal and vertical lines
        If Math.Abs(RctLn.N_1 - RctLn.N_2) < 0.001 Then
            '// Horizontal line; This is a hit
            Return True
        End If
        If Math.Abs(RctLn.E_1 - RctLn.E_2) < 0.001 Then
            '// Vertical line; This is a hit
            Return True
        End If

        Dim mLine As Double = (Ln.N_2 - Ln.N_1) / (Ln.E_2 - Ln.E_1)
        Dim bLine As Double = Ln.N_1 - Ln.E_1 * mLine


        '// at this time, if the intersection point with
        '// a side of the rectangle is inside that side
        '// then we have a hit
        Dim NInt As Double, EInt As Double

        '// Bottom side (N const)
        EInt = (Rect.N_1 - bLine) / mLine
        If (EInt >= Rect.E_1) AndAlso (EInt <= Rect.E_2) Then
            Return True
        End If

        '// Top side (N const)
        EInt = (Rect.N_2 - bLine) / mLine
        If (EInt >= Rect.E_1) AndAlso (EInt <= Rect.E_2) Then
            Return True
        End If

        '// Left side
        NInt = mLine * Rect.E_1 + bLine
        If (NInt >= Rect.N_1) AndAlso (NInt <= Rect.N_2) Then
            Return True
        End If

        '// Right side
        NInt = mLine * Rect.E_2 + bLine
        If (NInt >= Rect.N_1) AndAlso (NInt <= Rect.N_2) Then
            Return True
        End If

        GC.Collect()
        GC.WaitForPendingFinalizers()
        '// Hopeless
        Return False

    End Function
    '============================================================================================='

    '---------------------------------------------------------------------------------------------'
    '// Checks if two rectangles aligned with axes intersect
    Public Shared Function Intersect_RectRect( _
        ByRef Rect1 As FSK_RECT, _
        ByRef Rect2 As FSK_RECT) As Boolean

        Dim dTmp As Double

        If (Rect1.N_1 > Rect1.N_2) Then
            dTmp = Rect1.N_1
            Rect1.N_1 = Rect1.N_2
            Rect1.N_2 = dTmp
        End If
        If (Rect1.E_1 > Rect1.E_2) Then
            dTmp = Rect1.E_1
            Rect1.E_1 = Rect1.E_2
            Rect1.E_2 = dTmp
        End If

        If (Rect2.N_1 > Rect2.N_2) Then
            dTmp = Rect2.N_1
            Rect2.N_1 = Rect2.N_2
            Rect2.N_2 = dTmp
        End If
        If (Rect2.E_1 > Rect2.E_2) Then
            dTmp = Rect2.E_1
            Rect2.E_1 = Rect2.E_2
            Rect2.E_2 = dTmp
        End If

        If (Rect2.N_1 > Rect1.N_2) Then
            '// Rect2 is Above the Rect1
            Return False
        End If
        If (Rect2.N_2 < Rect1.N_1) Then
            '// Rect2 is Below the Rect1
            Return False
        End If
        If (Rect2.E_1 > Rect1.E_2) Then
            '// Rect2 is To the right of Rect1
            Return False
        End If
        If (Rect2.E_2 < Rect1.E_1) Then
            '// Rect2 is To the left of Rect1
            Return False
        End If

        GC.Collect()
        GC.WaitForPendingFinalizers()
        '// they do intersect
        Return True
    End Function
    '============================================================================================='

    '// --------------------------------------------------------------------- '
    '// Will either get selected polyline or will ask the user to select one
    Public Shared Function SelectPolyline(ByRef acTrans As Transaction, _
                                   ByRef acDoc As Document, _
                                   ByRef acPoly As Polyline, _
                                   Optional ByVal bOnlyLines As Boolean = True, _
                                   Optional ByVal bAllowIntersect As Boolean = False, _
                                         Optional ByVal sMsg As String = Nothing) _
                                   As Boolean

        Dim peo As PromptEntityOptions
        If sMsg Is Nothing Then
            sMsg = CMain._T(TX.SEL_POLY)
        End If
        '' Get the PickFirst selection set
        Dim acSSPrompt As PromptSelectionResult = acDoc.Editor.SelectImplied()
        '' If the prompt status is OK, objects were selected before
        '' the command was started
        If acSSPrompt.Status = PromptStatus.OK Then
            Dim acSSet As SelectionSet = acSSPrompt.Value
            For Each sobj As SelectedObject In acSSet
                Dim TheObj As DBObject
                TheObj = acTrans.GetObject(sobj.ObjectId, OpenMode.ForRead)
                If (TypeOf TheObj Is Polyline) Then
                    If acPoly Is Nothing Then
                        acPoly = DirectCast(TheObj, Polyline)
                    Else
                        '// more than one polylines selected
                        GoTo HaveUserSelect
                    End If
                End If
            Next
            If (acPoly Is Nothing) Then
                GoTo HaveUserSelect
            End If
        Else
HaveUserSelect:
            peo = New PromptEntityOptions(vbLf & sMsg & ": ")
            peo.SetRejectMessage(vbLf & CMain._T(TX.ERR_OBJTY) & "!")
            peo.AddAllowedClass(GetType(Autodesk.AutoCAD.DatabaseServices.Polyline), False)
            Dim per As PromptEntityResult = acDoc.Editor.GetEntity(peo)
            If per.Status <> PromptStatus.OK Then Return False
            acPoly = DirectCast( _
                acTrans.GetObject(per.ObjectId, OpenMode.ForRead),  _
                      Polyline)
        End If
        If (bOnlyLines = True) Then
            If acPoly.IsOnlyLines = False Then
                CMain.AlertUser(TX.ERR_PLYLNS)
                GoTo HaveUserSelect
            End If
        End If
        If (bAllowIntersect = False) Then
            Dim p3Dc As New Point3dCollection
            acPoly.IntersectWith( _
                    acPoly, _
                    Intersect.OnBothOperands, _
                    p3Dc, 0, 0)
            If (p3Dc.Count > acPoly.NumberOfVertices) Then
                CMain.AlertUser(TX.ERR_PLYINT)
                GoTo HaveUserSelect
            End If
        End If

        GC.Collect()
        GC.WaitForPendingFinalizers()
        Return True

    End Function
    '// ===================================================================== '

    '// --------------------------------------------------------------------- '
    '// Create a paralel line to the one provded through this point
    Public Shared Sub DoParalel(ByRef LnBase As FSK_LINE, _
                                 ByVal dN As Double, _
                                 ByVal dE As Double, _
                                 ByRef LnOut As FSK_LINE)
        LnOut.m = LnBase.m
        LnOut.bVert = LnBase.bVert
        If LnBase.bVert Then
            ' We have a vertical line; can't use slope
            LnOut.N_1 = LnBase.N_1
            LnOut.N_2 = LnBase.N_2
            LnOut.E_1 = dE
            LnOut.E_2 = dE
            LnOut.b = 0 '// infinity, actually
        Else
            '// pick one of the points to be provided input
            LnOut.N_1 = dN
            LnOut.E_1 = dE

            '// Compute Y intercept
            LnOut.b = dN - LnOut.m * dE
            '// The other one may be the Y intercept
            '// if we don't have already that
            If Math.Abs(LnOut.b - dN) > MARGIN Then
                LnOut.N_2 = LnOut.b
                LnOut.E_2 = 0
            Else
                LnOut.E_2 = LnBase.E_1 * 2
                LnOut.N_2 = LnOut.m * LnOut.E_2 + LnOut.b
            End If
        End If

    End Sub
    '// ===================================================================== '

    '// --------------------------------------------------------------------- '
    '// Checks if a point is part of a line (not a segment)
    Public Shared Function IsPartOfLine(ByRef LnBase As FSK_LINE, _
                                 ByVal dN As Double, _
                                 ByVal dE As Double) _
                                 As Boolean

        '// Enshure that picked point is not on the line
        If (LnBase.bVert) Then
            If (Math.Abs(LnBase.E_2 - dE) > CMain.MARGIN) Then
                Return False
            End If
            Return True
        Else
            Dim d1sq As Double = Math.Pow(LnBase.N_1 - dN, 2) + _
                                 Math.Pow(LnBase.E_1 - dE, 2)
            Dim d2sq As Double = Math.Pow(LnBase.N_2 - dN, 2) + _
                                 Math.Pow(LnBase.E_2 - dE, 2)
            Dim dLsq As Double = Math.Pow(LnBase.N_2 - LnBase.N_1, 2) + _
                                 Math.Pow(LnBase.E_2 - LnBase.E_1, 2)
            If (Math.Abs(d1sq + d2sq - dLsq) > CMain.MARGIN) Then
                Return False
            End If
            Return True
        End If

    End Function
    '// ===================================================================== '

    '// --------------------------------------------------------------------- '
    '// Computes the distance from a point to a line
    Public Shared Function DistToLine(ByRef LnBase As FSK_LINE, _
                                 ByVal dN As Double, _
                                 ByVal dE As Double) _
                                 As Double
        If LnBase.bVert Then
            ' We have a vertical line; can't use slope
            Return Math.Abs(dE - LnBase.E_1)
        Else
            Dim m2 As Double
            m2 = -1 / LnBase.m
            Dim b2 As Double = dN - m2 * dE
            Dim dEInt As Double = -1 * (b2 - LnBase.b) / (m2 - LnBase.m)
            Dim dNInt As Double = LnBase.m * dEInt + LnBase.b
            Return Math.Sqrt( _
                Math.Pow(dEInt - dE, 2) + _
                Math.Pow(dNInt - dN, 2))

        End If
    End Function
    '// ===================================================================== '


    '// --------------------------------------------------------------------- '
    '// Create a perpendicular line to the one provded through this point
    Public Shared Sub DoPerp(ByRef LnBase As FSK_LINE, _
                                 ByVal dN As Double, _
                                 ByVal dE As Double, _
                                 ByRef LnOut As FSK_LINE)
        If LnBase.bVert Then
            ' We have a vertical line; can't use slope
            LnOut.N_1 = dN
            LnOut.N_2 = dN
            LnOut.E_1 = LnBase.E_1
            LnOut.E_2 = LnBase.E_2
            LnOut.m = 0
            LnOut.b = dN
        Else
            '// pick one of the points to be provided input
            LnOut.N_1 = dN
            LnOut.E_1 = dE

            LnOut.m = -1 / LnBase.m
            LnOut.b = dN - LnOut.m * dE

            '// The other one may be the Y intercept
            '// if we don't have already that
            If Math.Abs(LnOut.b - dN) > MARGIN Then
                LnOut.N_2 = LnOut.b
                LnOut.E_2 = 0
            Else
                LnOut.E_2 = LnBase.E_1 * 2
                LnOut.N_2 = LnOut.m * LnOut.E_2 + LnOut.b
            End If
        End If
    End Sub
    '// ===================================================================== '

    '// --------------------------------------------------------------------- '
    '// appends a point into the chain
    Public Shared Sub AddPtToChain(ByRef pct As PtMg, _
                                  ByVal dNorth As Double, _
                                  ByVal dEast As Double)

        If (pct.iAlc <= pct.iUsd) Then
            pct.iAlc = pct.iAlc + 16
            ReDim Preserve pct.pt(0 To pct.iAlc - 1)
        End If
        pct.pt(pct.iUsd).i = 0
        pct.pt(pct.iUsd).N_1 = dNorth
        pct.pt(pct.iUsd).E_1 = dEast
        pct.iUsd = pct.iUsd + 1
    End Sub
    Public Shared Sub AddPtToChain(ByRef pct As PtMg, _
                                   ByRef pt As FSK_PT)

        If (pct.iAlc <= pct.iUsd) Then
            pct.iAlc = pct.iAlc + 16
            ReDim Preserve pct.pt(0 To pct.iAlc - 1)
        End If
        pct.pt(pct.iUsd).i = 0
        pct.pt(pct.iUsd).N_1 = pt.N_1
        pct.pt(pct.iUsd).E_1 = pt.E_1
        pct.iUsd = pct.iUsd + 1
    End Sub
    '// ===================================================================== '

    '// --------------------------------------------------------------------- '
    '// appends a point into the chain
    Public Shared Sub AddPtToChain3D(ByRef pct As PtMg3D, _
                                  ByVal iNr As String, _
                                  ByVal dNorth As Double, _
                                  ByVal dEast As Double, _
                                  ByVal dZ As Double)

        If (pct.iAlc <= pct.iUsd) Then
            pct.iAlc = pct.iAlc + 16
            ReDim Preserve pct.pt(0 To pct.iAlc - 1)
        End If
        pct.pt(pct.iUsd).Name = iNr
        pct.pt(pct.iUsd).North = dNorth
        pct.pt(pct.iUsd).East = dEast
        pct.pt(pct.iUsd).Height = dZ
        pct.iUsd = pct.iUsd + 1
    End Sub
    Public Shared Sub AddPtToChain3D(ByRef pct As PtMg3D, _
                                   ByRef pt As FSK_PT3D)

        If (pct.iAlc <= pct.iUsd) Then
            pct.iAlc = pct.iAlc + 16
            ReDim Preserve pct.pt(0 To pct.iAlc - 1)
        End If
        pct.pt(pct.iUsd) = pt
        pct.iUsd = pct.iUsd + 1
    End Sub
    '// ===================================================================== '


    '// --------------------------------------------------------------------- '
    '// appends a line into the chain
    Public Shared Sub AddLnToChain(ByRef ln As LnMg, _
                                  ByVal dNorth1 As Double, _
                                  ByVal dEast1 As Double, _
                                  ByVal dNorth2 As Double, _
                                  ByVal dEast2 As Double)

        Dim dDst As Double
        If (ln.iAlc <= ln.iUsd) Then
            ln.iAlc = ln.iAlc + 16
            ReDim Preserve ln.ln(0 To ln.iAlc - 1)
        End If
        With ln.ln(ln.iUsd)
            .E_1 = dEast1
            .N_1 = dNorth1
            .E_2 = dEast2
            .N_2 = dNorth2

            dDst = (.E_2 - .E_1)
            If (Math.Abs(dDst) < CMain.MARGIN) Then
                .bVert = True
                .m = 0
                .b = 0
            Else
                .bVert = False
                .m = ((.N_2 - .N_1) / dDst)
                .b = .N_1 - .m * .E_1
            End If
        End With
        ln.iUsd = ln.iUsd + 1
    End Sub
    '// ===================================================================== '

    '// --------------------------------------------------------------------- '
    '// appends a line into the chain
    Public Shared Sub AddLnToChain(ByRef ln As LnMg, _
                                  ByRef lIn As FSK_LINE)

        If (ln.iAlc <= ln.iUsd) Then
            ln.iAlc = ln.iAlc + 16
            ReDim Preserve ln.ln(0 To ln.iAlc - 1)
        End If
        With ln.ln(ln.iUsd)
            .E_1 = lIn.E_1
            .N_1 = lIn.N_1
            .E_2 = lIn.E_2
            .N_2 = lIn.N_2
            .b = lIn.b
            .m = lIn.m
            .bVert = lIn.bVert
        End With
        ln.iUsd = ln.iUsd + 1
    End Sub
    '// ===================================================================== '


    '// --------------------------------------------------------------------- '
    '// returns the index of the line that was found or 
    Public Shared Function IsLnInChain(ByRef ln As LnMg, _
                                  ByVal dNorth1 As Double, _
                                  ByVal dEast1 As Double, _
                                  ByVal dNorth2 As Double, _
                                  ByVal dEast2 As Double) As Integer

        If ln.iUsd = 0 Then
            Return Integer.MaxValue
        End If
        Dim i As Integer
        For i = 0 To ln.iUsd - 1
            With ln.ln(i)
                If ((Math.Abs(dEast1 - .E_1) < CMain.MARGIN) AndAlso _
                    (Math.Abs(dEast2 - .E_2) < CMain.MARGIN) AndAlso _
                    (Math.Abs(dNorth1 - .N_1) < CMain.MARGIN) AndAlso _
                    (Math.Abs(dNorth2 - .N_2) < CMain.MARGIN)) Then
                    Return i
                ElseIf _
                    ((Math.Abs(dEast1 - .E_2) < CMain.MARGIN) AndAlso _
                    (Math.Abs(dEast2 - .E_1) < CMain.MARGIN) AndAlso _
                    (Math.Abs(dNorth1 - .N_2) < CMain.MARGIN) AndAlso _
                    (Math.Abs(dNorth2 - .N_1) < CMain.MARGIN)) Then
                    Return i
                End If
            End With
        Next
        Return Integer.MaxValue
    End Function
    '// ===================================================================== '

    '// --------------------------------------------------------------------- '
    '// returns the index of the line that was found or 
    Public Shared Function IsLnInChain(ByRef ln As LnMg, _
                                  ByRef lIn As FSK_LINE) As Integer

        If ln.iUsd = 0 Then
            Return Integer.MaxValue
        End If
        Dim i As Integer
        For i = 0 To ln.iUsd - 1
            With ln.ln(i)
                If ((Math.Abs(lIn.E_1 - .E_1) < CMain.MARGIN) AndAlso _
                    (Math.Abs(lIn.E_2 - .E_2) < CMain.MARGIN) AndAlso _
                    (Math.Abs(lIn.N_1 - .N_1) < CMain.MARGIN) AndAlso _
                    (Math.Abs(lIn.N_2 - .N_2) < CMain.MARGIN)) Then
                    Return i
                ElseIf _
                    ((Math.Abs(lIn.E_1 - .E_2) < CMain.MARGIN) AndAlso _
                    (Math.Abs(lIn.E_2 - .E_1) < CMain.MARGIN) AndAlso _
                    (Math.Abs(lIn.N_1 - .N_2) < CMain.MARGIN) AndAlso _
                    (Math.Abs(lIn.N_2 - .N_1) < CMain.MARGIN)) Then
                    Return i
                End If
            End With
        Next
        Return Integer.MaxValue
    End Function
    '// ===================================================================== '


    'Public Sub GetInters()'    Dim doc As Document = acadApp.DocumentManager.MdiActiveDocument
    '    Dim db As Database = doc.Database
    '    Dim ed As Editor = doc.Editor
    '    Dim tr As Transaction = db.TransactionManager.StartTransaction
    '    Try
    '    Using (tr)
    '        Dim opt As New PromptEntityOptions(vbLf & "Select line: ")
    '        opt.SetRejectMessage(vbLf & "Select line only")
    '        opt.AllowNone = False
    '        opt.AllowObjectOnLockedLayer = True
    '        opt.AddAllowedClass(GetType(Line), True)
    '        Dim res As PromptEntityResult = ed.GetEntity(opt)
    '        If res.Status <> PromptStatus.OK Then Return

    '        Dim lid As ObjectId = res.ObjectId
    '        opt.AddAllowedClass(GetType(Polyline), True)
    '        opt.SetRejectMessage(vbLf & "Select polyline only")
    '        opt.Message = vbLf & "Select polyline: "
    '        res = ed.GetEntity(opt)
    '        If res.Status <> PromptStatus.OK Then Return

    '        Dim pid As ObjectId = res.ObjectId
    '        Dim pts As Point3dCollection = New Point3dCollection()
    '        ed.WriteMessage(vbLf & "{0} <> {1};", lid, pid)

    '        Dim enl As Line = CType(tr.GetObject(lid, OpenMode.ForRead), Line)
    '        Dim enp As Polyline = CType(tr.GetObject(pid, OpenMode.ForRead), Polyline)
    '        Dim plane As Plane = New Plane(ed.CurrentUserCoordinateSystem.CoordinateSystem3d.Origin, ed.CurrentUserCoordinateSystem.CoordinateSystem3d. Zaxis)

    '        enl.IntersectWith(enp, Intersect.OnBothOperands, plane, pts, 0, 0)
    '        ed.WriteMessage(vbLf & "Number of intersections: {0}", pts.Count)
    '        Dim i As Integer = 1
    '        For Each pt As Point3d In pts
    '        ed.WriteMessage(vbLf & "Point number {0}: ({1}, {2}, {3})", i, pt.X, pt.Y, pt.Z)
    '        i += 1
    '        Next
    '        tr.Commit()
    '    End Using
    '    Catch ex As Autodesk.AutoCAD.Runtime.Exception
    '        ed.WriteMessage(vbLf & "{0}", ex.Message)
    '    End Try
    'End Sub

    '// --------------------------------------------------------------------- '
    '// get a double from a text box
    Public Shared Function GetTxDbl(ByRef txb As System.Windows.Forms.TextBox, _
                            ByRef dOut As Double) As Boolean
        Dim bRet As Boolean = False
        Try
            If (String.IsNullOrEmpty(txb.Text)) Then
                dOut = 0
                MsgBox(CStr(CMain._T(TX.NAN)), MsgBoxStyle.Critical, _
                       CMain._T(TX.ERR))
                txb.Text = "0"
                txb.SelectAll()
                txb.Focus()
                Return bRet
            End If
            dOut = CDbl(txb.Text)
            Debug.Print("<" & txb.Text & "> = " & dOut.ToString())
            bRet = True
        Catch ex As System.Exception
            dOut = 0
            MsgBox(CStr(txb.Text & vbNewLine & _
                   CMain._T(TX.NAN)), MsgBoxStyle.Critical, _
                   CMain._T(TX.ERR))
            txb.SelectAll()
            txb.Focus()
        End Try
        Return bRet
    End Function
    '// ===================================================================== '

    '// --------------------------------------------------------------------- '
    '// Get a double from a text
    Public Shared Function GetDbl( _
        ByRef sTx As String, _
        ByRef dOut As Double) As Boolean

        Dim bRet As Boolean = False
        Try
            dOut = CDbl(sTx)
            bRet = True
        Catch ex As System.Exception
        End Try
        Return bRet
    End Function
    '// ===================================================================== '

    '// --------------------------------------------------------------------- '
    '// Get a integer from a text
    Public Shared Function GetInt( _
        ByRef sTx As String, _
        ByRef dOut As Integer) As Boolean

        Dim bRet As Boolean = False
        Try
            dOut = CInt(sTx)
            bRet = True
        Catch ex As System.Exception
        End Try
        Return bRet
    End Function
    '// ===================================================================== '

    '// --------------------------------------------------------------------- '
    Public Shared Function GetScaleFromUser(ByRef bOk As Boolean) As Double

        Dim acDoc As Document = Autodesk.AutoCAD.ApplicationServices. _
            Application.DocumentManager.MdiActiveDocument
        If acDoc Is Nothing Then
            bOk = False
            Return 0
        End If

        Dim dRes As Double
        Dim bRes As Boolean = False

        Try

            Dim ppo As PromptPointOptions
            Dim ppr As PromptPointResult
            Dim dN1 As Double, dE1 As Double
            Dim dN2 As Double, dE2 As Double
            Dim dN3 As Double, dE3 As Double
            Dim dN4 As Double, dE4 As Double
            Dim dDn As Double
            Dim dDe As Double
            Dim dD1 As Double
            Dim dD2 As Double

            '// get first segment
            ppo = New PromptPointOptions(vbLf & CMain._T(TX.SYM_SCL1) & ":")

            ppr = acDoc.Editor.GetPoint(ppo)
            If ppr.Status <> PromptStatus.OK Then Exit Try
            dN1 = ppr.Value.Y
            dE1 = ppr.Value.X

            ppo.BasePoint = ppr.Value
            ppo.UseBasePoint = True
            ppo.Message = vbLf & CMain._T(TX.SYM_SCL2) & ":"
            Do
                ppr = acDoc.Editor.GetPoint(ppo)
                If ppr.Status <> PromptStatus.OK Then Exit Try
                dDn = ppr.Value.Y - dN1
                dDe = ppr.Value.X - dE1

                If Math.Abs(dDn) > CMain.MARGIN Then
                    Exit Do
                End If
                If Math.Abs(dDe) > CMain.MARGIN Then
                    Exit Do
                End If
                CMain.AlertUser(TX.ERR_PTCLOSE)
            Loop
            dN2 = ppr.Value.Y
            dE2 = ppr.Value.X
            dD1 = Math.Sqrt(dDn * dDn + dDe * dDe)


            '// get second segment
            ppo.UseBasePoint = False
            ppo.Message = vbLf & CMain._T(TX.SYM_SCL3) & ":"
            ppo.Keywords.Add(CMain._T(TX.SAME))
            ppr = acDoc.Editor.GetPoint(ppo)
            If ppr.Status = PromptStatus.OK Then
                dN3 = ppr.Value.Y
                dE3 = ppr.Value.X
            ElseIf ppr.Status = PromptStatus.Keyword Then
                dN3 = dN1
                dE3 = dE1
            Else
                Exit Try
            End If


            ppo.BasePoint = ppr.Value
            ppo.UseBasePoint = True
            ppo.Message = vbLf & CMain._T(TX.SYM_SCL4) & ":"
            Do
                ppr = acDoc.Editor.GetPoint(ppo)
                If ppr.Status <> PromptStatus.OK Then Exit Try
                dDn = ppr.Value.Y - dN1
                dDe = ppr.Value.X - dE1

                If Math.Abs(dDn) > CMain.MARGIN Then
                    Exit Do
                End If
                If Math.Abs(dDe) > CMain.MARGIN Then
                    Exit Do
                End If
                CMain.AlertUser(TX.ERR_PTCLOSE)
            Loop
            dN4 = ppr.Value.Y
            dE4 = ppr.Value.X
            dD2 = Math.Sqrt(dDn * dDn + dDe * dDe)

            dRes = dD2 / dD1
            bRes = True
        Catch ex As System.Exception
            CMain.DebugException(ex)
        End Try
        GC.Collect()
        GC.WaitForPendingFinalizers()
        bOk = bRes
        Return dRes

    End Function
    '// ===================================================================== '

    '// --------------------------------------------------------------------- '
    '// Finds closest point to a given point
    Public Shared Function GetClosesPt_Pt( _
        ByRef pts As PtMg, _
        ByRef dN As Double, _
        ByRef dE As Double, _
        ByRef ptOut As FSK_PT) As Boolean


        If pts.iUsd = 0 Then
            '// no intersection
            Return False
        ElseIf pts.iUsd = 1 Then
            '// there's no doubt; this one point will be used
            ptOut = pts.pt(0)
            Return True
        End If

        Dim dstRet As Double
        Dim iRet As Integer
        ptOut.i = 0

        Dim dCrtDst As Double
        iRet = 0
        dstRet = _
            Math.Pow(pts.pt(0).E_1 - dE, 2) + _
            Math.Pow(pts.pt(0).N_1 - dN, 2)

        For i As Integer = 1 To pts.iUsd - 1

            dCrtDst = _
                Math.Pow(pts.pt(i).E_1 - dE, 2) + _
                Math.Pow(pts.pt(i).N_1 - dN, 2)

            If dCrtDst < dstRet Then
                iRet = i
                dstRet = dCrtDst
            End If
        Next
        ptOut.E_1 = pts.pt(iRet).E_1
        ptOut.N_1 = pts.pt(iRet).N_1
        ptOut.i = iRet
        GC.Collect()
        GC.WaitForPendingFinalizers()
        Return True
    End Function
    '// ===================================================================== '

    '// --------------------------------------------------------------------- '
    '// create a line from 2D acad points
    Public Shared Sub GetLnFromAcadPt2D( _
                        ByRef LnPrp As FSK_LINE, _
                        ByRef pt1 As Point2d, _
                        ByVal dAng1 As Double)

        LnPrp.E_1 = pt1.X
        LnPrp.N_1 = pt1.Y
        LnPrp.E_2 = pt1.X + 1000 * Math.Cos(dAng1)
        LnPrp.N_2 = pt1.Y + 1000 * Math.Sin(dAng1)
        Dim dDstE As Double = LnPrp.E_2 - LnPrp.E_1
        Dim dDstN As Double = LnPrp.N_2 - LnPrp.N_1
        If Math.Abs(dDstE) < CMain.MARGIN Then
            LnPrp.m = 0
            LnPrp.b = 0
            LnPrp.bVert = True
            Return
        End If
        LnPrp.m = dDstN / dDstE
        LnPrp.b = LnPrp.N_1 - LnPrp.m * LnPrp.E_1
        Return
    End Sub
    Public Shared Sub GetLnFromAcadPt2D( _
                        ByRef LnPrp As FSK_LINE, _
                        ByVal pt1N As Double, _
                        ByVal pt1E As Double, _
                        ByVal dAng1 As Double)

        LnPrp.E_1 = pt1E
        LnPrp.N_1 = pt1N
        LnPrp.E_2 = pt1E + 1000 * Math.Cos(dAng1)
        LnPrp.N_2 = pt1N + 1000 * Math.Sin(dAng1)
        Dim dDstE As Double = LnPrp.E_2 - LnPrp.E_1
        Dim dDstN As Double = LnPrp.N_2 - LnPrp.N_1
        If Math.Abs(dDstE) < CMain.MARGIN Then
            LnPrp.m = 0
            LnPrp.b = 0
            LnPrp.bVert = True
            Return
        End If
        LnPrp.m = dDstN / dDstE
        LnPrp.b = LnPrp.N_1 - LnPrp.m * LnPrp.E_1
        Return
    End Sub
    Public Shared Sub GetLnFromAcadPt2D( _
                        ByRef LnPrp As FSK_LINE, _
                        ByRef pt1 As Point2d, _
                        ByRef pt2 As Point2d)

        LnPrp.E_1 = pt1.X
        LnPrp.N_1 = pt1.Y
        LnPrp.E_2 = pt2.X
        LnPrp.N_2 = pt2.Y
        Dim dDstE As Double = LnPrp.E_2 - LnPrp.E_1
        Dim dDstN As Double = LnPrp.N_2 - LnPrp.N_1
        If Math.Abs(dDstE) < CMain.MARGIN Then
            LnPrp.m = 0
            LnPrp.b = 0
            LnPrp.bVert = True
            Return
        End If
        LnPrp.m = dDstN / dDstE
        LnPrp.b = LnPrp.N_1 - LnPrp.m * LnPrp.E_1
        Return
    End Sub
    Public Shared Sub GetLnFromAcadPt2D( _
                        ByRef LnPrp As FSK_LINE, _
                        ByVal pt1N As Double, _
                        ByVal pt1E As Double, _
                        ByRef pt2 As Point2d)

        LnPrp.E_1 = pt1E
        LnPrp.N_1 = pt1N
        LnPrp.E_2 = pt2.X
        LnPrp.N_2 = pt2.Y
        Dim dDstE As Double = LnPrp.E_2 - LnPrp.E_1
        Dim dDstN As Double = LnPrp.N_2 - LnPrp.N_1
        If Math.Abs(dDstE) < CMain.MARGIN Then
            LnPrp.m = 0
            LnPrp.b = 0
            LnPrp.bVert = True
            Return
        End If
        LnPrp.m = dDstN / dDstE
        LnPrp.b = LnPrp.N_1 - LnPrp.m * LnPrp.E_1
        Return
    End Sub
    Public Shared Sub GetLnFromAcadPt2D( _
                        ByRef LnPrp As FSK_LINE, _
                        ByVal pt1N As Double, _
                        ByVal pt1E As Double, _
                        ByVal pt2N As Double, _
                        ByVal pt2E As Double)

        LnPrp.E_1 = pt1E
        LnPrp.N_1 = pt1N
        LnPrp.E_2 = pt2E
        LnPrp.N_2 = pt2N
        Dim dDstE As Double = LnPrp.E_2 - LnPrp.E_1
        Dim dDstN As Double = LnPrp.N_2 - LnPrp.N_1
        If Math.Abs(dDstE) < CMain.MARGIN Then
            LnPrp.m = 0
            LnPrp.b = 0
            LnPrp.bVert = True
            Return
        End If
        LnPrp.m = dDstN / dDstE
        LnPrp.b = LnPrp.N_1 - LnPrp.m * LnPrp.E_1
        Return
    End Sub
    '// ===================================================================== '

    '// --------------------------------------------------------------------- '
    '// get the lenght of a line
    Public Shared Function GetLnLen(ByRef LnPrp As FSK_LINE) As Double

        Dim dDstE As Double = LnPrp.E_2 - LnPrp.E_1
        Dim dDstN As Double = LnPrp.N_2 - LnPrp.N_1
        Return Math.Sqrt(dDstE * dDstE + dDstN * dDstN)
    End Function
    Public Shared Function GetLnLen(ByRef p1 As FSK_PT, _
                                    ByRef p2 As FSK_PT) As Double

        Dim dDstE As Double = p2.E_1 - p1.E_1
        Dim dDstN As Double = p2.N_1 - p1.N_1
        Return Math.Sqrt(dDstE * dDstE + dDstN * dDstN)
    End Function
    Public Shared Function GetLnLen(ByVal dN_1 As Double, _
                              ByVal dE_1 As Double, _
                              ByVal dN_2 As Double, _
                              ByVal dE_2 As Double) As Double

        Dim dDstE As Double = dE_2 - dE_1
        Dim dDstN As Double = dN_2 - dN_1
        Return Math.Sqrt(dDstE * dDstE + dDstN * dDstN)
    End Function
    '// ===================================================================== '

End Class



' Implements a comparer for ListView columns.
        '// code copied from
'// http://www.vb-helper.com/howto_net_listview_sort_clicked_column.html
Class ListViewComparer
    Implements IComparer

    Private m_ColumnNumber As Integer
    Private m_SortOrder As Windows.Forms.SortOrder

    Property ColNr As Integer
        Get
            Return m_ColumnNumber
        End Get
        Set(ByVal value As Integer)
            m_ColumnNumber = value
        End Set
    End Property
    Property CrtSO As Windows.Forms.SortOrder
        Get
            Return m_SortOrder
        End Get
        Set(ByVal value As Windows.Forms.SortOrder)
            m_SortOrder = value
        End Set
    End Property


    Public Sub New(ByVal column_number As Integer, ByVal _
        sort_order As Windows.Forms.SortOrder)
        m_ColumnNumber = column_number
        m_SortOrder = sort_order
    End Sub

    ' Compare the items in the appropriate column
    ' for objects x and y.
    Public Function Compare(ByVal x As Object, ByVal y As _
        Object) As Integer Implements _
        System.Collections.IComparer.Compare
        Dim item_x As Windows.Forms.ListViewItem = DirectCast(x, _
            Windows.Forms.ListViewItem)
        Dim item_y As Windows.Forms.ListViewItem = DirectCast(y, _
            Windows.Forms.ListViewItem)

        ' Get the sub-item values.
        Dim string_x As String
        If item_x.SubItems.Count <= m_ColumnNumber Then
            string_x = ""
        Else
            string_x = item_x.SubItems(m_ColumnNumber).Text
        End If

        Dim string_y As String
        If item_y.SubItems.Count <= m_ColumnNumber Then
            string_y = ""
        Else
            string_y = item_y.SubItems(m_ColumnNumber).Text
        End If

        ' Compare them.
        If m_SortOrder = Windows.Forms.SortOrder.Ascending Then
            If IsNumeric(string_x) And IsNumeric(string_y) _
                Then
                Return Val(string_x).CompareTo(Val(string_y))
            ElseIf IsDate(string_x) And IsDate(string_y) _
                Then
                Return DateTime.Parse(string_x).CompareTo(DateTime.Parse(string_y))
            Else
                Return String.Compare(string_x, string_y)
            End If
        Else
            If IsNumeric(string_x) And IsNumeric(string_y) _
                Then
                Return Val(string_y).CompareTo(Val(string_x))
            ElseIf IsDate(string_x) And IsDate(string_y) _
                Then
                Return DateTime.Parse(string_y).CompareTo(DateTime.Parse(string_x))
            Else
                Return String.Compare(string_y, string_x)
            End If
        End If
        GC.Collect()
        GC.WaitForPendingFinalizers()
    End Function






End Class
 


    '//  CLASS    =============================================================== '
    '//
    '//
    '//
    '//
    '//  FUNCTIONS    ----------------------------------------------------------- '
    
    '//  FUNCTIONS    =========================================================== '
    '//
    '//
    '//
    '//
    '// ------------------------------------------------------------------------- '
    '// ========================================================================= '
    
    
    
